From 978b0798e5eae281e7f4c6ea30ce435413f657a6 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 3 May 2022 14:04:38 -0500 Subject: [PATCH 1/6] OPL: fix possible crash --- src/engine/platform/opl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index dfe83d364..dc121a06c 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -940,6 +940,7 @@ void* DivPlatformOPL::getChanState(int ch) { } DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) { + if (ch>=18) return NULL; return oscBuf[ch]; } From 49ff39abee9fa38601d7d77117edd0e9048c091e Mon Sep 17 00:00:00 2001 From: Laurens Holst Date: Tue, 3 May 2022 19:32:17 +0200 Subject: [PATCH 2/6] AY8930: Fix tone and noise period in expanded mode. By doubling the internal clock frequency. In expanded mode, the same tone period is an octave higher than in compat mode. In expanded mode, the noise period is twice as fast as currently implemented. See https://github.com/tildearrow/furnace/pull/416 --- src/engine/platform/ay8930.cpp | 4 ++-- src/engine/platform/sound/ay8910.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 5b823606b..3fec732b5 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -27,7 +27,7 @@ #define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} #define immWrite2(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } -#define CHIP_DIVIDER 8 +#define CHIP_DIVIDER 4 const char* regCheatSheetAY8930[]={ "FreqL_A", "00", @@ -645,7 +645,7 @@ void DivPlatformAY8930::setFlags(unsigned int flags) { chipClock=COLOR_NTSC/2.0; break; } - rate=chipClock/8; + rate=chipClock/4; for (int i=0; i<3; i++) { oscBuf[i]->rate=rate; } diff --git a/src/engine/platform/sound/ay8910.cpp b/src/engine/platform/sound/ay8910.cpp index 8bb387885..4d19e7de5 100644 --- a/src/engine/platform/sound/ay8910.cpp +++ b/src/engine/platform/sound/ay8910.cpp @@ -1064,7 +1064,7 @@ void ay8910_device::sound_stream_update(short** outputs, int outLen) { tone = &m_tone[chan]; const int period = std::max(1,tone->period); - tone->count += is_expanded_mode() ? 16 : 1; + tone->count += is_expanded_mode() ? 16 : (m_feature & PSG_HAS_EXPANDED_MODE) ? 2 : 1; while (tone->count >= period) { tone->duty_cycle = (tone->duty_cycle - 1) & 0x1f; @@ -1080,7 +1080,7 @@ void ay8910_device::sound_stream_update(short** outputs, int outLen) * channels. */ m_count_noise = 0; - m_prescale_noise ^= 1; + m_prescale_noise = (m_prescale_noise + 1) & ((m_feature & PSG_HAS_EXPANDED_MODE) ? 3 : 1); if (!m_prescale_noise || is_expanded_mode()) // AY8930 noise generator rate is twice compares as compatibility mode { @@ -1469,7 +1469,7 @@ ay8910_device::ay8910_device(device_type type, unsigned int clock, m_noise_latch(0), m_mode(0), m_env_step_mask((!(feature & PSG_HAS_EXPANDED_MODE)) && (psg_type == PSG_TYPE_AY) ? 0x0f : 0x1f), - m_step( (!(feature & PSG_HAS_EXPANDED_MODE)) && (psg_type == PSG_TYPE_AY) ? 2 : 1), + m_step( (feature & PSG_HAS_EXPANDED_MODE) || (psg_type == PSG_TYPE_AY) ? 2 : 1), m_zero_is_off( (!(feature & PSG_HAS_EXPANDED_MODE)) && (psg_type == PSG_TYPE_AY) ? 1 : 0), m_par( (!(feature & PSG_HAS_EXPANDED_MODE)) && (psg_type == PSG_TYPE_AY) ? &ay8910_param : &ym2149_param), m_par_env( (!(feature & PSG_HAS_EXPANDED_MODE)) && (psg_type == PSG_TYPE_AY) ? &ay8910_param : &ym2149_param_env), @@ -1502,7 +1502,7 @@ void ay8910_device::set_type(psg_type_t psg_type) else { m_env_step_mask = 0x1f; - m_step = 1; + m_step = (m_feature & PSG_HAS_EXPANDED_MODE) ? 2 : 1; m_zero_is_off = 0; m_par = &ym2149_param; m_par_env = &ym2149_param_env; From 1a6a132a59207ab084832841469d0c9cab0cbfd4 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 3 May 2022 16:22:24 -0500 Subject: [PATCH 3/6] aaaaaa --- src/engine/sysDef.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 11e34187e..14ab512f1 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -319,6 +319,18 @@ int DivEngine::minVGMVersion(DivSystem which) { #define IS_YM2610 (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT || sysOfChan[ch]==DIV_SYSTEM_YM2610_FULL || sysOfChan[ch]==DIV_SYSTEM_YM2610_FULL_EXT || sysOfChan[ch]==DIV_SYSTEM_YM2610B || sysOfChan[ch]==DIV_SYSTEM_YM2610B_EXT) #define IS_OPM_LIKE (sysOfChan[ch]==DIV_SYSTEM_YM2151 || sysOfChan[ch]==DIV_SYSTEM_OPZ) +#define OP_EFFECT_MULTI(x,c,op,mask) \ + case x: \ + dispatchCmd(DivCommand(c,ch,op,effectVal&mask)); \ + break; + +#define OP_EFFECT_SINGLE(x,c,maxOp,mask) \ + case x: \ + if ((effectVal>>4)>=0 && (effectVal>>4)<=maxOp) { \ + dispatchCmd(DivCommand(c,ch,(effectVal>>4)-1,effectVal&mask)); \ + } \ + break; + // define systems like: // sysDefs[DIV_SYSTEM_ID]=new DivSysDef( // "Name", "Name (japanese, optional)", fileID, fileID_DMF, channels, isFM, isSTD, vgmVersion, From 9dfa2f9cbbada463979da6e5d3253a924d836184 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 3 May 2022 16:53:25 -0500 Subject: [PATCH 4/6] dev91 - it's a breaking change --- src/engine/engine.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index 572fd90bc..d15838942 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -45,8 +45,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev90" -#define DIV_ENGINE_VERSION 90 +#define DIV_VERSION "dev91" +#define DIV_ENGINE_VERSION 91 // for imports #define DIV_VERSION_MOD 0xff01 From 30e60f643cbd584abf8093edd60183262fd289c0 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 3 May 2022 17:37:17 -0500 Subject: [PATCH 5/6] add extra FM effects to effect post handler see #38 the last thing left to do is to put these effects on the dispatch code --- papers/doc/7-systems/opz.md | 4 +- src/engine/dispatch.h | 2 + src/engine/playback.cpp | 2 + src/engine/sysDef.cpp | 80 +++++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/papers/doc/7-systems/opz.md b/papers/doc/7-systems/opz.md index dd69c85c8..c7812740e 100644 --- a/papers/doc/7-systems/opz.md +++ b/papers/doc/7-systems/opz.md @@ -46,10 +46,10 @@ no plans have been made for TX81Z MIDI passthrough, because: - `28xy`: set reverb of operator. - `x` is the operator (1-4). a value of 0 means "all operators". - `y` is the value. -- `29xy`: set EG shift of operator. +- `2Axy`: set waveform of operator. - `x` is the operator (1-4). a value of 0 means "all operators". - `y` is the value. -- `2Axy`: set waveform of operator. +- `2Bxy`: set EG shift of operator. - `x` is the operator (1-4). a value of 0 means "all operators". - `y` is the value. - `2Fxx`: enable envelope hard reset. diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 8799c7821..bf80c645e 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -78,6 +78,8 @@ enum DivDispatchCmds { DIV_CMD_FM_SUS, // (op, value) DIV_CMD_FM_WS, // (op, value) DIV_CMD_FM_SSG, // (op, value) + DIV_CMD_FM_REV, // (op, value) + DIV_CMD_FM_EG_SHIFT, // (op, value) DIV_CMD_FM_FB, // (value) DIV_CMD_FM_MULT, // (op, value) DIV_CMD_FM_FINE, // (op, value) diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 5572fea05..224838e84 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -80,6 +80,8 @@ const char* cmdName[]={ "FM_SUS", "FM_WS", "FM_SSG", + "FM_REV", + "FM_EG_SHIFT", "FM_FB", "FM_MULT", "FM_FINE", diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 14ab512f1..70768fe0f 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -448,6 +448,54 @@ void DivEngine::registerSystems() { dispatchCmd(DivCommand(DIV_CMD_AY_AUTO_ENVELOPE,ch,effectVal)); } break; + // fixed frequency effects on OPZ + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x35: case 0x36: case 0x37: + if (sysOfChan[ch]==DIV_SYSTEM_OPZ) { + dispatchCmd(DivCommand(DIV_CMD_FM_FIXFREQ,ch,0,((effect&7)<<8)|effectVal)); + } + break; + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: + if (sysOfChan[ch]==DIV_SYSTEM_OPZ) { + dispatchCmd(DivCommand(DIV_CMD_FM_FIXFREQ,ch,1,((effect&7)<<8)|effectVal)); + } + break; + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x45: case 0x46: case 0x47: + if (sysOfChan[ch]==DIV_SYSTEM_OPZ) { + dispatchCmd(DivCommand(DIV_CMD_FM_FIXFREQ,ch,2,((effect&7)<<8)|effectVal)); + } + break; + case 0x48: case 0x49: case 0x4a: case 0x4b: + case 0x4c: case 0x4d: case 0x4e: case 0x4f: + if (sysOfChan[ch]==DIV_SYSTEM_OPZ) { + dispatchCmd(DivCommand(DIV_CMD_FM_FIXFREQ,ch,3,((effect&7)<<8)|effectVal)); + } + break; + // extra FM effects here + OP_EFFECT_SINGLE(0x50,DIV_CMD_FM_AM,4,1); + OP_EFFECT_SINGLE(0x51,DIV_CMD_FM_SL,4,15); + OP_EFFECT_SINGLE(0x52,DIV_CMD_FM_RR,4,15); + OP_EFFECT_SINGLE(0x53,DIV_CMD_FM_DT,4,7); + OP_EFFECT_SINGLE(0x54,DIV_CMD_FM_RS,4,3); + OP_EFFECT_SINGLE(0x55,DIV_CMD_FM_SSG,4,(IS_OPM_LIKE?3:15)); + + OP_EFFECT_MULTI(0x56,DIV_CMD_FM_DR,-1,31); + OP_EFFECT_MULTI(0x57,DIV_CMD_FM_DR,0,31); + OP_EFFECT_MULTI(0x58,DIV_CMD_FM_DR,1,31); + OP_EFFECT_MULTI(0x59,DIV_CMD_FM_DR,2,31); + OP_EFFECT_MULTI(0x5a,DIV_CMD_FM_DR,3,31); + + OP_EFFECT_MULTI(0x5b,DIV_CMD_FM_D2R,-1,31); + OP_EFFECT_MULTI(0x5c,DIV_CMD_FM_D2R,0,31); + OP_EFFECT_MULTI(0x5d,DIV_CMD_FM_D2R,1,31); + OP_EFFECT_MULTI(0x5e,DIV_CMD_FM_D2R,2,31); + OP_EFFECT_MULTI(0x5f,DIV_CMD_FM_D2R,3,31); + + OP_EFFECT_SINGLE(0x28,DIV_CMD_FM_REV,4,7); + OP_EFFECT_SINGLE(0x2a,DIV_CMD_FM_WS,4,7); + OP_EFFECT_SINGLE(0x2b,DIV_CMD_FM_EG_SHIFT,4,3); default: return false; } @@ -479,6 +527,21 @@ void DivEngine::registerSystems() { case 0x1b: // AR op2 dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,1,effectVal&31)); break; + + // extra FM effects here + OP_EFFECT_SINGLE(0x50,DIV_CMD_FM_AM,2,1); + OP_EFFECT_SINGLE(0x51,DIV_CMD_FM_SL,2,15); + OP_EFFECT_SINGLE(0x52,DIV_CMD_FM_RR,2,15); + OP_EFFECT_SINGLE(0x53,DIV_CMD_FM_VIB,2,1); + OP_EFFECT_SINGLE(0x54,DIV_CMD_FM_RS,2,3); + OP_EFFECT_SINGLE(0x55,DIV_CMD_FM_SUS,2,1); + + OP_EFFECT_MULTI(0x56,DIV_CMD_FM_DR,-1,15); + OP_EFFECT_MULTI(0x57,DIV_CMD_FM_DR,0,15); + OP_EFFECT_MULTI(0x58,DIV_CMD_FM_DR,1,15); + + OP_EFFECT_SINGLE(0x5b,DIV_CMD_FM_KSR,2,1); + OP_EFFECT_SINGLE(0x2a,DIV_CMD_FM_WS,4,7); default: return false; } @@ -528,6 +591,23 @@ void DivEngine::registerSystems() { case 0x1d: // AR op4 dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&15)); break; + + // extra FM effects here + OP_EFFECT_SINGLE(0x50,DIV_CMD_FM_AM,4,1); + OP_EFFECT_SINGLE(0x51,DIV_CMD_FM_SL,4,15); + OP_EFFECT_SINGLE(0x52,DIV_CMD_FM_RR,4,15); + OP_EFFECT_SINGLE(0x53,DIV_CMD_FM_VIB,4,1); + OP_EFFECT_SINGLE(0x54,DIV_CMD_FM_RS,4,3); + OP_EFFECT_SINGLE(0x55,DIV_CMD_FM_SUS,4,1); + + OP_EFFECT_MULTI(0x56,DIV_CMD_FM_DR,-1,15); + OP_EFFECT_MULTI(0x57,DIV_CMD_FM_DR,0,15); + OP_EFFECT_MULTI(0x58,DIV_CMD_FM_DR,1,15); + OP_EFFECT_MULTI(0x59,DIV_CMD_FM_DR,2,15); + OP_EFFECT_MULTI(0x5a,DIV_CMD_FM_DR,3,15); + + OP_EFFECT_SINGLE(0x5b,DIV_CMD_FM_KSR,4,1); + default: return false; } From 28e7b8672819f66cdcb24248ae6cd0b0f0305448 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 3 May 2022 17:41:10 -0500 Subject: [PATCH 6/6] fix sample saving --- src/engine/sample.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 3aec450b0..e46c267d1 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -71,7 +71,7 @@ bool DivSample::save(const char* path) { } sf_command(f, SFC_SET_INSTRUMENT, &inst, sizeof(inst)); - sf_write_short(f,data16,length16); + sf_writef_short(f,data16,samples); sf_close(f);