diff --git a/README.md b/README.md index 7145931bb..47ab0be35 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,8 @@ the following effects are provided: - if `y` is 1 then the envelope will affect this channel. - `23xx`: set envelope period low byte. - `24xx`: set envelope period high byte. +- `25xx`: slide envelope period up. +- `26xx`: slide envelope period down. a lower envelope period will make the envelope run faster. diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 09070e71a..63ed82162 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -54,10 +54,13 @@ enum DivDispatchCmds { DIV_CMD_C64_FILTER_RESET, DIV_CMD_C64_DUTY_RESET, DIV_CMD_C64_EXTENDED, + DIV_CMD_C64_FINE_DUTY, + DIV_CMD_C64_FINE_CUTOFF, DIV_CMD_AY_ENVELOPE_SET, DIV_CMD_AY_ENVELOPE_LOW, DIV_CMD_AY_ENVELOPE_HIGH, + DIV_CMD_AY_ENVELOPE_SLIDE, DIV_ALWAYS_SET_VOLUME, diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index 3d78a5dcc..bbda090d5 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -195,6 +195,11 @@ int DivPlatformC64::dispatch(DivCommand c) { rWrite(c.chan*7+2,chan[c.chan].duty&0xff); rWrite(c.chan*7+3,chan[c.chan].duty>>8); break; + case DIV_CMD_C64_FINE_DUTY: + chan[c.chan].duty=c.value; + rWrite(c.chan*7+2,chan[c.chan].duty&0xff); + rWrite(c.chan*7+3,chan[c.chan].duty>>8); + break; case DIV_CMD_WAVE: chan[c.chan].wave=c.value; rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active); @@ -220,6 +225,10 @@ int DivPlatformC64::dispatch(DivCommand c) { filtCut=c.value*2047/100; updateFilter(); break; + case DIV_CMD_C64_FINE_CUTOFF: + filtCut=c.value; + updateFilter(); + break; case DIV_CMD_C64_RESONANCE: if (c.value>15) c.value=15; filtRes=c.value; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index b27562134..84c3e39f9 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -99,6 +99,26 @@ void DivPlatformYM2610::tick() { ((chan[4].psgMode&2)<<2)| ((chan[5].psgMode&2)<<3)| ((chan[6].psgMode&2)<<4))); + + if (ayEnvSlide!=0) { + ayEnvSlideLow+=ayEnvSlide; + while (ayEnvSlideLow>7) { + ayEnvSlideLow-=8; + if (ayEnvPeriod<0xffff) { + ayEnvPeriod++; + immWrite(0x0b,ayEnvPeriod); + immWrite(0x0c,ayEnvPeriod>>8); + } + } + while (ayEnvSlideLow<-7) { + ayEnvSlideLow+=8; + if (ayEnvPeriod>0) { + ayEnvPeriod--; + immWrite(0x0b,ayEnvPeriod); + immWrite(0x0c,ayEnvPeriod>>8); + } + } + } // FM for (int i=0; i<4; i++) { @@ -462,6 +482,10 @@ int DivPlatformYM2610::dispatch(DivCommand c) { immWrite(0x0b,ayEnvPeriod); immWrite(0x0c,ayEnvPeriod>>8); break; + case DIV_CMD_AY_ENVELOPE_SLIDE: + if (c.chan<4 || c.chan>6) break; + ayEnvSlide=c.value; + break; case DIV_ALWAYS_SET_VOLUME: return 0; break; @@ -543,6 +567,8 @@ void DivPlatformYM2610::reset() { sampleBank=0; ayEnvPeriod=0; ayEnvMode=0; + ayEnvSlide=0; + ayEnvSlideLow=0; delay=0; diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index edcc38b35..6a31632b8 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -56,6 +56,8 @@ class DivPlatformYM2610: public DivDispatch { short pendingWrites[512]; unsigned char ayEnvMode; unsigned short ayEnvPeriod; + short ayEnvSlideLow; + short ayEnvSlide; int octave(int freq); int toFreq(int freq); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 424e4ef63..8db32ee03 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -66,10 +66,13 @@ const char* cmdName[DIV_CMD_MAX]={ "C64_FILTER_RESET", "C64_DUTY_RESET", "C64_EXTENDED", + "C64_FINE_DUTY", + "C64_FINE_CUTOFF", "AY_ENVELOPE_SET", "AY_ENVELOPE_LOW", "AY_ENVELOPE_HIGH", + "AY_ENVELOPE_SLIDE", "ALWAYS_SET_VOLUME" }; @@ -261,6 +264,16 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_HIGH,ch,effectVal)); } break; + case 0x25: // UNOFFICIAL: Neo Geo PSG envelope slide up + if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { + dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SLIDE,ch,-effectVal)); + } + break; + case 0x26: // UNOFFICIAL: Neo Geo PSG envelope slide down + if (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT) { + dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SLIDE,ch,effectVal)); + } + break; default: return false; } @@ -297,6 +310,16 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char case 0x1e: // extended dispatchCmd(DivCommand(DIV_CMD_C64_EXTENDED,ch,effectVal)); break; + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: // fine duty + dispatchCmd(DivCommand(DIV_CMD_C64_FINE_DUTY,ch,((effect&0x0f)<<8)|effectVal)); + break; + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: // fine cutoff + dispatchCmd(DivCommand(DIV_CMD_C64_FINE_CUTOFF,ch,((effect&0x07)<<8)|effectVal)); + break; default: return false; } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 11a5d47ed..ef911a6ba 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1434,6 +1434,8 @@ void FurnaceGUI::drawPattern() { ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]); } else if (pat->data[i][index]<0x30) { ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_SECONDARY]); + } else if (pat->data[i][index]<0x48) { + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_SYS_PRIMARY]); } else if (pat->data[i][index]<0xe0) { ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_PATTERN_EFFECT_INVALID]); } else if (pat->data[i][index]<0xf0) {