From 6e79e84e539db5421a3e971d9c29265b9987921f Mon Sep 17 00:00:00 2001 From: Waldemar Pawlaszek Date: Mon, 21 Feb 2022 12:41:06 +0100 Subject: [PATCH] Added panning and load LFSR commands. --- src/engine/dispatch.h | 2 ++ src/engine/platform/lynx.cpp | 39 +++++++++++++++++++++++++++--------- src/engine/platform/lynx.h | 10 +++++---- src/engine/playback.cpp | 7 +++++++ src/engine/vgmOps.cpp | 11 +++++++--- src/gui/gui.cpp | 1 + src/gui/settings.cpp | 1 + 7 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 0740c7834..b90481589 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -97,6 +97,8 @@ enum DivDispatchCmds { DIV_CMD_SAA_ENVELOPE, + DIV_CMD_LYNX_LFSR_LOAD, + DIV_ALWAYS_SET_VOLUME, DIV_CMD_MAX diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 83e33d38c..533fbdabb 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -10,6 +10,7 @@ #define WRITE_BACKUP(ch,v) rWrite(0x24+(ch<<3),(v)) #define WRITE_CONTROL(ch,v) rWrite(0x25+(ch<<3),(v)) #define WRITE_OTHER(ch,v) rWrite(0x27+(ch<<3),(v)) +#define WRITE_ATTEN(ch,v) rWrite((0x40+ch),(v)) #define CHIP_DIVIDER 64 @@ -68,6 +69,19 @@ const char* regCheatSheetLynx[]={ const char** DivPlatformLynx::getRegisterSheet() { return regCheatSheetLynx; +} + +const char* DivPlatformLynx::getEffectName(unsigned char effect) { + switch (effect) + { + 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: + return "3xxx: Load LFSR (0 to FFF)"; + break; + } + return NULL; } void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len) { @@ -101,21 +115,20 @@ void DivPlatformLynx::tick() { } if (chan[i].freqChanged) { - chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true); - if (chan[i].resetLFSR) { - chan[i].resetLFSR=false; - WRITE_LFSR(i, 0); - WRITE_OTHER(i, 0); + if (chan[i].lfsr >= 0) { + WRITE_LFSR(i, (chan[i].lfsr&0xff)); + WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4)); + chan[i].lfsr=-1; } + chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true); if (chan[i].std.hadDuty) { - chan[i].duty = chan[i].std.duty; + chan[i].duty=chan[i].std.duty; WRITE_FEEDBACK(i, chan[i].duty.feedback); } WRITE_BACKUP(i, chan[i].fd.backup); WRITE_CONTROL(i, (chan[i].fd.clockDivider|0x18|chan[i].duty.int_feedback7)); } - else if (chan[i].std.hadDuty) - { + else if (chan[i].std.hadDuty) { chan[i].duty = chan[i].std.duty; WRITE_FEEDBACK(i, chan[i].duty.feedback); WRITE_CONTROL(i, (chan[i].fd.clockDivider|0x18|chan[i].duty.int_feedback7)); @@ -129,9 +142,10 @@ int DivPlatformLynx::dispatch(DivCommand c) { if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); chan[c.chan].freqChanged=true; - chan[c.chan].resetLFSR=true; chan[c.chan].note=c.value; chan[c.chan].actualNote=c.value; + if (chan[c.chan].lfsr<0) + chan[c.chan].lfsr=0; } chan[c.chan].active=true; WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127))); @@ -142,6 +156,10 @@ int DivPlatformLynx::dispatch(DivCommand c) { WRITE_VOLUME(c.chan, 0); chan[c.chan].std.init(NULL); break; + case DIV_CMD_LYNX_LFSR_LOAD: + chan[c.chan].freqChanged=true; + chan[c.chan].lfsr=c.value; + break; case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_ENV_RELEASE: chan[c.chan].std.release(); @@ -159,6 +177,9 @@ int DivPlatformLynx::dispatch(DivCommand c) { if (chan[c.chan].active) WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127))); } break; + case DIV_CMD_PANNING: + WRITE_ATTEN(c.chan, c.value); + break; case DIV_CMD_GET_VOLUME: if (chan[c.chan].std.hasVol) { return chan[c.chan].vol; diff --git a/src/engine/platform/lynx.h b/src/engine/platform/lynx.h index e0f095b8b..a45cdb837 100644 --- a/src/engine/platform/lynx.h +++ b/src/engine/platform/lynx.h @@ -22,20 +22,22 @@ class DivPlatformLynx: public DivDispatch { }; struct Channel { + DivMacroInt std; MikeyFreqDiv fd; MikeyDuty duty; - int baseFreq, pitch, note, actualNote; + int baseFreq, pitch, note, actualNote, lfsr; unsigned char ins; - bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, resetLFSR; + bool active, insChanged, freqChanged, keyOn, keyOff, inPorta; signed char vol, outVol; - DivMacroInt std; Channel(): + std(), fd(0), duty(0), baseFreq(0), pitch(0), note(0), actualNote(0), + lfsr(-1), ins(-1), active(false), insChanged(true), @@ -43,7 +45,6 @@ class DivPlatformLynx: public DivDispatch { keyOn(false), keyOff(false), inPorta(false), - resetLFSR(false), vol(127), outVol(127) {} }; @@ -66,6 +67,7 @@ class DivPlatformLynx: public DivDispatch { void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); const char** getRegisterSheet(); + const char* getEffectName( unsigned char effect ); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformLynx(); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 858113496..301bc434e 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -218,6 +218,13 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe return false; } break; + case DIV_SYSTEM_LYNX: + if (effect>=0x30 && effect<0x40) { + int value = ((int)(effect&0x0f)<<8)|effectVal; + dispatchCmd(DivCommand(DIV_CMD_LYNX_LFSR_LOAD,ch,value)); + break; + } + return false; default: return false; } diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 31c3609ab..990891314 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -262,11 +262,16 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write break; case DIV_SYSTEM_LYNX: w->writeC(0x4e); - w->writeC(0x40); - w->writeC(0xff); //panning + w->writeC(0x44); + w->writeC(0xff); //stereo attenuation select w->writeC(0x4e); w->writeC(0x50); - w->writeC(0x00); //stereo + w->writeC(0x00); //stereo channel disable + for (int i=0; i<4; i++) { //stereo attenuation value + w->writeC(0x4e); + w->writeC(0x40+i); + w->writeC(0xff); + } break; default: break; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 617feacf3..a61a0bc7c 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4602,6 +4602,7 @@ bool FurnaceGUI::loop() { sysChangeOption(i,DIV_SYSTEM_TIA); sysChangeOption(i,DIV_SYSTEM_SAA1099); sysChangeOption(i,DIV_SYSTEM_AY8930); + sysChangeOption(i,DIV_SYSTEM_LYNX); ImGui::EndMenu(); } } diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index cf73921f8..8bf46a530 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -461,6 +461,7 @@ void FurnaceGUI::drawSettings() { UI_COLOR_CONFIG(GUI_COLOR_INSTR_POKEY,"POKEY"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_BEEPER,"PC Beeper"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_SWAN,"WonderSwan"); + UI_COLOR_CONFIG(GUI_COLOR_INSTR_MIKEY,"Lynx"); UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,"Other/Unknown"); ImGui::TreePop(); }