From 76bd96706eba8d151b88c36155348a0e73da5a07 Mon Sep 17 00:00:00 2001 From: System64 <42580501+system64MC@users.noreply.github.com> Date: Mon, 3 Oct 2022 19:42:52 +0200 Subject: [PATCH 01/57] Update gui.h --- src/gui/gui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/gui.h b/src/gui/gui.h index 203fd20e8..45c43e56c 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1611,6 +1611,7 @@ class FurnaceGUI { // wave generator int waveGenBaseShape; + int waveInterpolation; float waveGenDuty; int waveGenPower; float waveGenInvertPoint; From 46b5e64415496177d6a48b774ce033b71065c2ad Mon Sep 17 00:00:00 2001 From: System64 <42580501+system64MC@users.noreply.github.com> Date: Mon, 3 Oct 2022 19:48:07 +0200 Subject: [PATCH 02/57] =?UTF-8?q?=E2=9C=A8=20added=20interpolations=20for?= =?UTF-8?q?=20wavetable=20resize?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/gui/waveEdit.cpp | 79 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 87f5ad38f..d3e5327cd 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -32,6 +32,13 @@ const char* waveGenBaseShapes[4]={ "Pulse" }; +const char* waveInterpolations[4] = { + "None", + "Linear", + "Cosine", + "Cubic" +}; + const float multFactors[17]={ M_PI, 2*M_PI, @@ -519,17 +526,71 @@ void FurnaceGUI::drawWaveEdit() { if (waveGenScaleX<2) waveGenScaleX=2; if (waveGenScaleX>256) waveGenScaleX=256; } + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + if (CWSliderInt("##WGInterpolation", &waveInterpolation, 0, 3, waveInterpolations[waveInterpolation])) { + if (waveInterpolation < 0) waveInterpolation = 0; + if (waveInterpolation > 3) waveInterpolation = 3; + //doGenerateWave(); + } ImGui::TableNextColumn(); if (ImGui::Button("Scale X")) { - if (waveGenScaleX>0 && wave->len!=waveGenScaleX) e->lockEngine([this,wave]() { - int origData[256]; - memcpy(origData,wave->data,wave->len*sizeof(int)); - for (int i=0; idata[i]=origData[i*wave->len/waveGenScaleX]; - } - wave->len=waveGenScaleX; - MARK_MODIFIED; - }); + if (waveGenScaleX > 0 && wave->len != waveGenScaleX) e->lockEngine([this, wave]() { + int origData[256]; + // Copy original wave to temp buffer + assert(wave->len <= 256); + memcpy(origData, wave->data, wave->len * sizeof(int)); + + float t = 0; // Index used into `origData` + + for (int i = 0; i < waveGenScaleX; i++, t += (float)wave->len / waveGenScaleX) { + + switch (waveInterpolation) + { + default: // No interpolation + { + wave->data[i] = origData[i * wave->len / waveGenScaleX]; + break; // No interpolation + } + case 0: + { + wave->data[i] = origData[i * wave->len / waveGenScaleX]; + break; + } + case 1: // Linear + { + int idx = t; // Implicitly floors `t` + int s0 = origData[(idx) % wave->len], s1 = origData[(idx + 1) % wave->len]; + double mu = (t - idx); + wave->data[i] = s0 + mu * s1 - (mu * s0); + break; + } + case 2: // Cosine + { + int idx = t; // Implicitly floors `t` + int s0 = origData[(idx) % wave->len], s1 = origData[(idx + 1) % wave->len]; + double mu = (t - idx); + double muCos = (1 - cos(mu * M_PI)) / 2; + wave->data[i] = s0 + muCos * s1 - (muCos * s0); + break; + } + case 3: // Cubic Spline + { + int idx = t; // Implicitly floors `t` + int s0 = origData[(idx) % wave->len], s1 = origData[(idx + 1) % wave->len], s2 = origData[(idx + 2) % wave->len], s3 = origData[(idx + 3) % wave->len]; + double a0, a1, a2, a3; + double mu = (t - idx); + double mu2 = mu * mu; + a0 = -0.5 * s0 + 1.5 * s1 - 1.5 * s2 + 0.5 * s3; + a1 = s0 - 2.5 * s1 + 2 * s2 - 0.5 * s3; + a2 = -0.5 * s0 + 0.5 * s2; + a3 = s1; + wave->data[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3); + } + } + } + wave->len = waveGenScaleX; + MARK_MODIFIED; + }); } ImGui::TableNextRow(); From 77f66642f4159e35d749d62ea1ecf91d984b9550 Mon Sep 17 00:00:00 2001 From: System64 <42580501+system64MC@users.noreply.github.com> Date: Tue, 4 Oct 2022 11:43:14 +0200 Subject: [PATCH 03/57] Update gui.cpp --- src/gui/gui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 2adbf89b1..cce640e02 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -5598,6 +5598,7 @@ FurnaceGUI::FurnaceGUI(): #endif hasACED(false), waveGenBaseShape(0), + waveInterpolation(0), waveGenDuty(0.5f), waveGenPower(1), waveGenInvertPoint(1.0f), From 88444e6f59bd4ade67036795ebb2da760fabb9be Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 12 Oct 2022 03:50:13 -0500 Subject: [PATCH 04/57] raise shields --- src/engine/sysDef.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index a0415bf6f..b4b1bfcc7 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1655,7 +1655,8 @@ void DivEngine::registerSystems() { ); sysDefs[DIV_SYSTEM_T6W28]=new DivSysDef( - "T6W28", NULL, 0xbf, 0, 4, false, true, 0, false, 0, + // 0x0a = wild guess. it may as well be 0x83 + "T6W28", NULL, 0xbf, 0x0a, 4, false, true, 0, false, 0, "an SN76489 derivative used in Neo Geo Pocket, has independent stereo volume and noise channel frequency.", {"Square 1", "Square 2", "Square 3", "Noise"}, {"S1", "S2", "S3", "NO"}, From 843d18290d731824cc6a6fc0eae347b8f8c8854b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 12 Oct 2022 04:05:09 -0500 Subject: [PATCH 05/57] T6W28: finish it up (mostly) --- src/engine/platform/t6w28.cpp | 43 +++++++++++++++++++++++++---------- src/engine/platform/t6w28.h | 6 ++--- src/engine/sysDef.cpp | 2 +- src/gui/insEdit.cpp | 5 ++++ src/gui/presets.cpp | 6 +++++ 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/engine/platform/t6w28.cpp b/src/engine/platform/t6w28.cpp index 6ff4cc12e..5361ce9c0 100644 --- a/src/engine/platform/t6w28.cpp +++ b/src/engine/platform/t6w28.cpp @@ -25,8 +25,6 @@ //#define rWrite(a,v) pendingWrites[a]=v; #define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } -#define CHIP_DIVIDER 16 - const char* regCheatSheetT6W28[]={ "Data0", "0", "Data1", "1", @@ -72,14 +70,21 @@ void DivPlatformT6W28::acquire(short* bufL, short* bufR, size_t start, size_t le } void DivPlatformT6W28::writeOutVol(int ch) { - int left=15-CLAMP(chan[ch].outVol+chan[ch].panL-15,0,15); - int right=15-CLAMP(chan[ch].outVol+chan[ch].panR-15,0,15); - rWrite(0,0x90|(ch<<5)|(isMuted[ch]?15:left)); - rWrite(1,0x90|(ch<<5)|(isMuted[ch]?15:right)); + if (chan[ch].active) { + int left=15-CLAMP(chan[ch].outVol+chan[ch].panL-15,0,15); + int right=15-CLAMP(chan[ch].outVol+chan[ch].panR-15,0,15); + rWrite(0,0x90|(ch<<5)|(isMuted[ch]?15:left)); + rWrite(1,0x90|(ch<<5)|(isMuted[ch]?15:right)); + } else { + rWrite(0,0x9f|(ch<<5)); + rWrite(1,0x9f|(ch<<5)); + } } void DivPlatformT6W28::tick(bool sysTick) { for (int i=0; i<4; i++) { + double CHIP_DIVIDER=16; + if (i==3) CHIP_DIVIDER=15; chan[i].std.next(); if (chan[i].std.vol.had) { chan[i].outVol=VOL_SCALE_LOG(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); @@ -91,6 +96,12 @@ void DivPlatformT6W28::tick(bool sysTick) { } chan[i].freqChanged=true; } + if (i==3 && chan[i].std.duty.had) { + if (chan[i].duty!=chan[i].std.duty.val) { + chan[i].duty=chan[i].std.duty.val&7; + rWrite(1,0xe0+chan[i].duty); + } + } if (chan[i].std.panL.had) { chan[i].panL=chan[i].std.panL.val&15; } @@ -109,12 +120,13 @@ void DivPlatformT6W28::tick(bool sysTick) { } chan[i].freqChanged=true; } + if (chan[i].std.phaseReset.had) { + rWrite(1,0xe0+chan[i].duty); + } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { - //DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE); chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER); if (chan[i].freq>1023) chan[i].freq=1023; if (i==3) { - rWrite(1,0xe7); rWrite(1,0x80|(2<<5)|(chan[3].freq&15)); rWrite(1,chan[3].freq>>4); } else { @@ -129,6 +141,8 @@ void DivPlatformT6W28::tick(bool sysTick) { } int DivPlatformT6W28::dispatch(DivCommand c) { + double CHIP_DIVIDER=16; + if (c.chan==3) CHIP_DIVIDER=15; switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PCE); @@ -142,6 +156,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) { chan[c.chan].macroInit(ins); if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; + writeOutVol(c.chan); } chan[c.chan].insChanged=false; break; @@ -150,6 +165,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) { chan[c.chan].active=false; chan[c.chan].keyOff=true; chan[c.chan].macroInit(NULL); + writeOutVol(c.chan); break; case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_ENV_RELEASE: @@ -166,8 +182,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) { chan[c.chan].vol=c.value; if (!chan[c.chan].std.vol.has) { chan[c.chan].outVol=c.value; - if (chan[c.chan].active) { - } + writeOutVol(c.chan); } } break; @@ -205,7 +220,9 @@ int DivPlatformT6W28::dispatch(DivCommand c) { break; } case DIV_CMD_STD_NOISE_MODE: - chan[c.chan].noise=c.value; + if (c.chan!=3) break; + chan[c.chan].duty=(((c.value&15)==1)?4:0)|((c.value>>4)&3); + rWrite(1,0xe0+chan[c.chan].duty); break; case DIV_CMD_PANNING: { chan[c.chan].panL=c.value>>4; @@ -226,7 +243,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) { chan[c.chan].inPorta=c.value; break; case DIV_CMD_GET_VOLMAX: - return 31; + return 15; break; case DIV_ALWAYS_SET_VOLUME: return 1; @@ -289,6 +306,8 @@ void DivPlatformT6W28::reset() { cycles=0; curChan=-1; delay=0; + // default noise mode + rWrite(1,0xe7); } bool DivPlatformT6W28::isStereo() { diff --git a/src/engine/platform/t6w28.h b/src/engine/platform/t6w28.h index bc4459914..5b5f1fc8f 100644 --- a/src/engine/platform/t6w28.h +++ b/src/engine/platform/t6w28.h @@ -29,8 +29,8 @@ class DivPlatformT6W28: public DivDispatch { struct Channel { int freq, baseFreq, pitch, pitch2, note; int ins; - unsigned char panL, panR; - bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise; + unsigned char panL, panR, duty; + bool active, insChanged, freqChanged, keyOn, keyOff, inPorta; signed char vol, outVol; DivMacroInt std; void macroInit(DivInstrument* which) { @@ -46,13 +46,13 @@ class DivPlatformT6W28: public DivDispatch { ins(-1), panL(15), panR(15), + duty(7), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), inPorta(false), - noise(false), vol(15), outVol(15) {} }; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index b4b1bfcc7..025b64d60 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1664,7 +1664,7 @@ void DivEngine::registerSystems() { {DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28}, {}, { - {0x20, {DIV_CMD_STD_NOISE_MODE, "20xy: Set noise mode (x: preset/variable; y: thin pulse/noise)"}} + {0x20, {DIV_CMD_STD_NOISE_MODE, "20xy: Set noise mode (x: 0-2 for preset, 3 for tonal; y: thin pulse/noise)"}} } ); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index a22e9dbe2..0f0d0d7ff 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4693,6 +4693,10 @@ void FurnaceGUI::drawInsEdit() { dutyLabel="Pulse Width"; dutyMax=255; } + if (ins->type==DIV_INS_T6W28) { + dutyLabel="Noise Type/Freq"; + dutyMax=7; + } if (ins->type==DIV_INS_AY8930) { dutyMax=ins->amiga.useSample?0:255; } @@ -4973,6 +4977,7 @@ void FurnaceGUI::drawInsEdit() { ins->type==DIV_INS_SU || ins->type==DIV_INS_MIKEY || ins->type==DIV_INS_ES5506 || + ins->type==DIV_INS_T6W28 || (ins->type==DIV_INS_X1_010 && ins->amiga.useSample)) { macroList.push_back(FurnaceGUIMacroDesc("Phase Reset",&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true)); } diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index a8c497037..e95b800db 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -270,6 +270,12 @@ void FurnaceGUI::initSystemPresets() { 0 } )); + cat.systems.push_back(FurnaceGUISysDef( + "Toshiba T6W28", { + DIV_SYSTEM_T6W28, 64, 0, 0, + 0 + } + )); cat.systems.push_back(FurnaceGUISysDef( "AY-3-8910", { DIV_SYSTEM_AY8910, 64, 0, 0, From a51840b801707ebae3fb38a85f81c1dee2e24a62 Mon Sep 17 00:00:00 2001 From: System64 <42580501+system64MC@users.noreply.github.com> Date: Wed, 12 Oct 2022 11:59:04 +0200 Subject: [PATCH 06/57] Fixed assertion crash and fixed a bug with the cubic interpolation. The interpolated waveform will now stay in phase. --- src/gui/waveEdit.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index d3e5327cd..6913ae372 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -537,7 +537,12 @@ void FurnaceGUI::drawWaveEdit() { if (waveGenScaleX > 0 && wave->len != waveGenScaleX) e->lockEngine([this, wave]() { int origData[256]; // Copy original wave to temp buffer - assert(wave->len <= 256); + // If longer than 256 samples, return + if (wave->len >= 256) + { + showError("ERROR : Wavetable longer than 256 samples!"); + return; + } memcpy(origData, wave->data, wave->len * sizeof(int)); float t = 0; // Index used into `origData` @@ -576,7 +581,7 @@ void FurnaceGUI::drawWaveEdit() { case 3: // Cubic Spline { int idx = t; // Implicitly floors `t` - int s0 = origData[(idx) % wave->len], s1 = origData[(idx + 1) % wave->len], s2 = origData[(idx + 2) % wave->len], s3 = origData[(idx + 3) % wave->len]; + int s0 = origData[((idx - 1 % wave->len + wave->len) % wave->len)], s1 = origData[(idx) % wave->len], s2 = origData[(idx + 1) % wave->len], s3 = origData[(idx + 2) % wave->len]; double a0, a1, a2, a3; double mu = (t - idx); double mu2 = mu * mu; From 0782e3af1de42293ebf2a91b32ea0304bc90f72a Mon Sep 17 00:00:00 2001 From: System64 <42580501+system64MC@users.noreply.github.com> Date: Wed, 12 Oct 2022 12:07:19 +0200 Subject: [PATCH 07/57] Update waveEdit.cpp --- src/gui/waveEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 6913ae372..524fdb402 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -538,7 +538,7 @@ void FurnaceGUI::drawWaveEdit() { int origData[256]; // Copy original wave to temp buffer // If longer than 256 samples, return - if (wave->len >= 256) + if (wave->len > 256) { showError("ERROR : Wavetable longer than 256 samples!"); return; From 78fc022c0486ab8f6188c081b7f1dc7afe1c141f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 12 Oct 2022 14:54:29 -0500 Subject: [PATCH 08/57] GUI: format --- src/gui/waveEdit.cpp | 134 +++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 69 deletions(-) diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 0d11c918f..4ceb7714b 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -33,11 +33,11 @@ const char* waveGenBaseShapes[4]={ "Pulse" }; -const char* waveInterpolations[4] = { - "None", - "Linear", - "Cosine", - "Cubic" +const char* waveInterpolations[4]={ + "None", + "Linear", + "Cosine", + "Cubic" }; const float multFactors[17]={ @@ -563,75 +563,71 @@ void FurnaceGUI::drawWaveEdit() { if (waveGenScaleX>256) waveGenScaleX=256; } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##WGInterpolation", &waveInterpolation, 0, 3, waveInterpolations[waveInterpolation])) { - if (waveInterpolation < 0) waveInterpolation = 0; - if (waveInterpolation > 3) waveInterpolation = 3; - //doGenerateWave(); + if (CWSliderInt("##WGInterpolation",&waveInterpolation,0,3,waveInterpolations[waveInterpolation])) { + if (waveInterpolation<0) waveInterpolation=0; + if (waveInterpolation>3) waveInterpolation=3; } ImGui::TableNextColumn(); if (ImGui::Button("Scale X")) { - if (waveGenScaleX > 0 && wave->len != waveGenScaleX) e->lockEngine([this, wave]() { - int origData[256]; - // Copy original wave to temp buffer - // If longer than 256 samples, return - if (wave->len > 256) - { - showError("ERROR : Wavetable longer than 256 samples!"); - return; + if (waveGenScaleX>0 && wave->len!=waveGenScaleX) e->lockEngine([this,wave]() { + int origData[256]; + // Copy original wave to temp buffer + // If longer than 256 samples, return + if (wave->len>256) { + showError("wavetable longer than 256 samples!"); + return; + } + memcpy(origData,wave->data,wave->len*sizeof(int)); + + float t=0; // Index used into `origData` + + for (int i=0; ilen/waveGenScaleX) { + switch (waveInterpolation) { + case 0: { + wave->data[i]=origData[i*wave->len/waveGenScaleX]; + break; } - memcpy(origData, wave->data, wave->len * sizeof(int)); - - float t = 0; // Index used into `origData` - - for (int i = 0; i < waveGenScaleX; i++, t += (float)wave->len / waveGenScaleX) { - - switch (waveInterpolation) - { - default: // No interpolation - { - wave->data[i] = origData[i * wave->len / waveGenScaleX]; - break; // No interpolation - } - case 0: - { - wave->data[i] = origData[i * wave->len / waveGenScaleX]; - break; - } - case 1: // Linear - { - int idx = t; // Implicitly floors `t` - int s0 = origData[(idx) % wave->len], s1 = origData[(idx + 1) % wave->len]; - double mu = (t - idx); - wave->data[i] = s0 + mu * s1 - (mu * s0); - break; - } - case 2: // Cosine - { - int idx = t; // Implicitly floors `t` - int s0 = origData[(idx) % wave->len], s1 = origData[(idx + 1) % wave->len]; - double mu = (t - idx); - double muCos = (1 - cos(mu * M_PI)) / 2; - wave->data[i] = s0 + muCos * s1 - (muCos * s0); - break; - } - case 3: // Cubic Spline - { - int idx = t; // Implicitly floors `t` - int s0 = origData[((idx - 1 % wave->len + wave->len) % wave->len)], s1 = origData[(idx) % wave->len], s2 = origData[(idx + 1) % wave->len], s3 = origData[(idx + 2) % wave->len]; - double a0, a1, a2, a3; - double mu = (t - idx); - double mu2 = mu * mu; - a0 = -0.5 * s0 + 1.5 * s1 - 1.5 * s2 + 0.5 * s3; - a1 = s0 - 2.5 * s1 + 2 * s2 - 0.5 * s3; - a2 = -0.5 * s0 + 0.5 * s2; - a3 = s1; - wave->data[i] = (a0 * mu * mu2 + a1 * mu2 + a2 * mu + a3); - } - } + case 1: { // Linear + int idx=t; // Implicitly floors `t` + int s0=origData[(idx)%wave->len]; + int s1=origData[(idx+1)%wave->len]; + double mu=(t-idx); + wave->data[i]=s0+mu*s1-(mu*s0); + break; } - wave->len = waveGenScaleX; - MARK_MODIFIED; - }); + case 2: { // Cosine + int idx=t; // Implicitly floors `t` + int s0=origData[(idx)%wave->len]; + int s1=origData[(idx+1)%wave->len]; + double mu=(t-idx); + double muCos=(1-cos(mu*M_PI))/2; + wave->data[i]=s0+muCos*s1-(muCos*s0); + break; + } + case 3: { // Cubic Spline + int idx=t; // Implicitly floors `t` + int s0=origData[((idx-1%wave->len+wave->len)%wave->len)]; + int s1=origData[(idx)%wave->len]; + int s2=origData[(idx+1)%wave->len]; + int s3=origData[(idx+2)%wave->len]; + double mu=(t-idx); + double mu2=mu*mu; + double a0=-0.5*s0+1.5*s1-1.5*s2+0.5*s3; + double a1=s0-2.5*s1+2*s2-0.5*s3; + double a2=-0.5*s0+0.5*s2; + double a3=s1; + wave->data[i]=(a0*mu*mu2+a1*mu2+a2*mu+a3); + break; + } + default: { // No interpolation + wave->data[i]=origData[i*wave->len/waveGenScaleX]; + break; + } + } + } + wave->len=waveGenScaleX; + MARK_MODIFIED; + }); } ImGui::TableNextRow(); From ef5d6cb554a7e8aa9f6ff5b3b88673d131f66dc8 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 12 Oct 2022 15:14:28 -0500 Subject: [PATCH 09/57] GUI: update credits --- src/gui/about.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 6610af220..99a279268 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -45,6 +45,7 @@ const char* aboutLine[]={ "laoo", "OPNA2608", "superctr", + "System64", "", "-- graphics/UI design --", "tildearrow", From 0f0c8b5567e8d531c51507d96c668e0cccc14b54 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 13 Oct 2022 03:30:05 -0500 Subject: [PATCH 10/57] Virtual Boy: noise length macro --- src/engine/platform/vb.cpp | 7 +++++++ src/gui/insEdit.cpp | 6 +++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index 29ff6a934..941f72eba 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -148,6 +148,13 @@ void DivPlatformVB::tick(bool sysTick) { } chan[i].freqChanged=true; } + if (i==5 && chan[i].std.duty.had) { + if ((chan[i].std.duty.val&7)!=((chan[i].envHigh>>4)&7)) { + chan[i].envHigh&=~0x70; + chan[i].envHigh|=(chan[i].std.duty.val&7)<<4; + writeEnv(i,true); + } + } if (chan[i].std.wave.had) { if (chan[i].wave!=chan[i].std.wave.val || chan[i].ws.activeChanged()) { chan[i].wave=chan[i].std.wave.val; diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 0f0d0d7ff..6b98ba71a 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4702,9 +4702,13 @@ void FurnaceGUI::drawInsEdit() { } if (ins->type==DIV_INS_TIA || ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SCC || ins->type==DIV_INS_PET || ins->type==DIV_INS_VIC || ins->type==DIV_INS_SEGAPCM || - ins->type==DIV_INS_FM || ins->type==DIV_INS_VBOY) { + ins->type==DIV_INS_FM) { dutyMax=0; } + if (ins->type==DIV_INS_VBOY) { + dutyLabel="Noise Length"; + dutyMax=7; + } if (ins->type==DIV_INS_PCE || ins->type==DIV_INS_NAMCO) { dutyLabel="Noise"; dutyMax=(ins->type==DIV_INS_PCE && !ins->amiga.useSample)?1:0; From b4b7ab86fb74e109145816d3a4512f2561a12682 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 13 Oct 2022 03:41:40 -0500 Subject: [PATCH 11/57] T6W28: honor poll --- src/engine/platform/t6w28.cpp | 4 ++-- src/engine/sysDef.cpp | 2 +- src/gui/insEdit.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/engine/platform/t6w28.cpp b/src/engine/platform/t6w28.cpp index 5361ce9c0..0abb39fa0 100644 --- a/src/engine/platform/t6w28.cpp +++ b/src/engine/platform/t6w28.cpp @@ -98,7 +98,7 @@ void DivPlatformT6W28::tick(bool sysTick) { } if (i==3 && chan[i].std.duty.had) { if (chan[i].duty!=chan[i].std.duty.val) { - chan[i].duty=chan[i].std.duty.val&7; + chan[i].duty=((chan[i].std.duty.val==1)?4:0)|3; rWrite(1,0xe0+chan[i].duty); } } @@ -221,7 +221,7 @@ int DivPlatformT6W28::dispatch(DivCommand c) { } case DIV_CMD_STD_NOISE_MODE: if (c.chan!=3) break; - chan[c.chan].duty=(((c.value&15)==1)?4:0)|((c.value>>4)&3); + chan[c.chan].duty=(((c.value&15)==1)?4:0)|3; rWrite(1,0xe0+chan[c.chan].duty); break; case DIV_CMD_PANNING: { diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 025b64d60..c0006061c 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1664,7 +1664,7 @@ void DivEngine::registerSystems() { {DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28, DIV_INS_T6W28}, {}, { - {0x20, {DIV_CMD_STD_NOISE_MODE, "20xy: Set noise mode (x: 0-2 for preset, 3 for tonal; y: thin pulse/noise)"}} + {0x20, {DIV_CMD_STD_NOISE_MODE, "20xx: Set noise length (0: short, 1: long)"}} } ); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 6b98ba71a..a01a3414a 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4694,8 +4694,8 @@ void FurnaceGUI::drawInsEdit() { dutyMax=255; } if (ins->type==DIV_INS_T6W28) { - dutyLabel="Noise Type/Freq"; - dutyMax=7; + dutyLabel="Noise Type"; + dutyMax=1; } if (ins->type==DIV_INS_AY8930) { dutyMax=ins->amiga.useSample?0:255; From 2cead0b7f998642ad483161d0bedc037638998fa Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 15 Oct 2022 04:00:41 -0500 Subject: [PATCH 12/57] Virtual Boy: phase reset macro --- src/engine/platform/vb.cpp | 2 +- src/gui/insEdit.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index 941f72eba..a57d92cdf 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -183,7 +183,7 @@ void DivPlatformVB::tick(bool sysTick) { chan[i].freqChanged=true; } if (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1) { - // ??? + chWrite(i,0x00,0x80); } if (chan[i].active) { if (chan[i].ws.tick() || (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1)) { diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index a01a3414a..ceda17a2e 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -4982,6 +4982,7 @@ void FurnaceGUI::drawInsEdit() { ins->type==DIV_INS_MIKEY || ins->type==DIV_INS_ES5506 || ins->type==DIV_INS_T6W28 || + ins->type==DIV_INS_VBOY || (ins->type==DIV_INS_X1_010 && ins->amiga.useSample)) { macroList.push_back(FurnaceGUIMacroDesc("Phase Reset",&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true)); } From 0d3042107fc7e4ab08edafaab320c00104f13408 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 15 Oct 2022 04:02:30 -0500 Subject: [PATCH 13/57] VERA: fix pan macro --- src/engine/platform/vera.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index cd76f414c..9ae1dbd56 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -174,6 +174,7 @@ void DivPlatformVERA::tick(bool sysTick) { if (i<16) { if (chan[i].std.panL.had) { chan[i].pan=chan[i].std.panL.val&3; + chan[i].pan=((chan[i].pan&1)<<1)|((chan[i].pan&2)>>1); rWriteHi(i,2,isMuted[i]?0:chan[i].pan); } } From 43d75712b3a74b20bef88ea2b633042f888ae04c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 15 Oct 2022 04:09:04 -0500 Subject: [PATCH 14/57] VERA: what is this? inconsistency? --- src/engine/platform/vera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index 9ae1dbd56..2966f9d1f 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -330,7 +330,7 @@ int DivPlatformVERA::dispatch(DivCommand c) { if (chan[c.chan].active && c.value2) { if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_VERA)); } - if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=calcNoteFreq(c.chan,chan[c.chan].note); + if (!chan[c.chan].inPorta && c.value && chan[c.chan].std.arp.will) chan[c.chan].baseFreq=calcNoteFreq(c.chan,chan[c.chan].note); chan[c.chan].inPorta=c.value; break; case DIV_CMD_STD_NOISE_MODE: From bf1639d9ba1a3356c3bbadfcf57669a1bb21028d Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 15 Oct 2022 04:17:42 -0500 Subject: [PATCH 15/57] NES: fix game_theme_tune_not_a_real_game_.dmf --- src/engine/platform/nes.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index a338cca8c..87f89a9dc 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -416,12 +416,10 @@ int DivPlatformNES::dispatch(DivCommand c) { if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } - if (!parent->song.brokenOutVol2) { - if (c.chan==2) { - rWrite(0x4000+c.chan*4,0xff); - } else { - rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); - } + if (c.chan==2) { + rWrite(0x4000+c.chan*4,0xff); + } else if (!parent->song.brokenOutVol2) { + rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6)); } break; case DIV_CMD_NOTE_OFF: From 67cfb331d4d8ca8c3da3c73e9c0cf1e3ac6b3ff0 Mon Sep 17 00:00:00 2001 From: Eris Lund <38136789+0x5066@users.noreply.github.com> Date: Sat, 15 Oct 2022 19:47:56 +0200 Subject: [PATCH 16/57] Add files via upload --- demos/Oh no, more sine waves.fur | Bin 0 -> 1990 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/Oh no, more sine waves.fur diff --git a/demos/Oh no, more sine waves.fur b/demos/Oh no, more sine waves.fur new file mode 100644 index 0000000000000000000000000000000000000000..760039c9c9adc76fda80d1aac1d126c8946c86fb GIT binary patch literal 1990 zcmaLUc`zFa9tZF^>e@Pr(w0ioi+T-hN%34o)zz&ArF9jh61Tbuu|(^>qX!aKTt(Lr zG>)KXwKNiSMMwyXN*dv{;&`#|b#`ao%+BneznR}}=KJ}5qf6MX^BGF_^SK@%5)xFwoZ)~V_`fNM;Gz~dW4;&Q?dH8vI@Vm60QSq$WnCxTb&mjlA|^(F#l zz1JJ>y!9dVy1F;d%`Nt^hF+Q7nSITkSFFFz<;S$N687)M;2c4|zcxC?pjn-5PjXo? zadgb?ZmBlyp@qpkbdZNR7bK6f`rAR+Kc=F!`X~yCO2Q1zd%zEl2+u=>v110vQ5LPm zi16Uz45Aa@vAgJuok(=I;3mr_aUxi-dkS#B*ED0HTJ`Y}#*}(r4hL`$Daj!12z*0` zZE`H+S05!ldn3d;kY_Mf0X4nC(cgbb9G(Vn76d!_l6_;r0tq}R#xzHO-#O-R6AGEX zn-#QBKUHeZA%5$uP8J0H9V&Xul)7o(+<9Bsd9A(Gxx;E(a?5VM4)W1EK@slmS_jc* z?|pS$boCDk%67$Xe0Qs2M1ATQLwf0FJ)zQgEjy^W`jTZyL~M|i=V{jQgN-!oLgATe(y__XNlkoUW0^f|d*x2jEHKse> z4fod~9?Wf7FW9}sx|C^jn)t@{5CfUmvi^1jvW4EorTWwqAciy#Iy-fyXssE}v6{Bi zHd?y5D8uaLW(fMX36QH^dPFN(-~Y6=H(vc#&P_UM?All!+9}ewsmN#uww~$tK)S`b z?l*Y3Il6Ff5BqMI1hugkmL{pr?OnHO=(K@SV<~v~tQ=jaZY_@D?;QY+KXqn$!p^K5 z5}P>rF#-G~Vu-b%*cT5EIM_tAGzJ$8rgzEX8dcqF$h=g!lw@c1o?F9Hl%A&RvHN!R zneW$Xnd?cA;NPJ05k(+QpVoRKY!_Dj|w@h|S7u#BGN!V2ad> zYl}p7LPYUxwU=sfBaCOO1%dI!=N)M{wLrsl=k#HV5;f&7cI%L9?M2_DF@_(};byb4 zH0HhQG$!~i7%vf>qa*NtRYI&_FIZOl7M`N*AcvGI5KD+Qnw{#f@)~kWr%V+z;b4ft zv;h+^+Wp)k|8=c+q9)|>L3|w@YBQ1Xzq#ef6lOWcZ>E)Bd16Ri?Wvu&%JTe~r;gd_ zpzV~pB(K8*ad9 z?XSkPXZRjoPZYJOU9pVGO}^sC$Y+Qvepkd#V36)tkkEm&J-Yv{ z7HT|KMt1p4myXUY5`7zJ2!tMnu4If6u1*2dCFzSQ);t5lpZCAA!sKvUo zN-S^kID&?H^m9+j)EgZFho&~j29?T;eu}P;{wnmPOieJAd$o6zD`YCHxnlVpbtR#G z$;Njd^}%Gk8sqSkW$@x|*&#tlr>|o+^ug9>{n%^04!#lS_IY6{tQFNaJ-(Ta;`pRL z#D;$H8%1prUznL5)mNZ@(nj>Y1PSjGR_at!u2Uyk;!T%9Fne2xz_uEnL+Pa&g^GUz Dq%Q^% literal 0 HcmV?d00001 From faf3063a72a651fc6c3c18ba945d15900289c898 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 15 Oct 2022 22:26:56 -0500 Subject: [PATCH 17/57] update readme (macOS workaround) --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 7efe2c2a0..116d87714 100644 --- a/README.md +++ b/README.md @@ -243,6 +243,17 @@ see [papers/](papers/doc/README.md). it's kind of incomplete, but at least the s this is due to Apple's application signing policy. a workaround is to right click on the Furnace app icon and select Open. +**as of Monterey, this workaround no longer works (especially on ARM).** yeah, Apple has decided to be strict on the matter. +if you happen to be on that version, use this workaround instead (on a Terminal): + +``` +xattr -d com.apple.quarantine /path/to/Furnace.app +``` + +(replace /path/to/ with the path where Furnace.app is located) + +you may need to log out and/or reboot after doing this. + > how do I use C64 absolute filter/duty? on Instrument Editor in the C64 tab there are two options to toggle these. From 489f56b91330bc58e423f085ce4d19bb7b505fa7 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 15 Oct 2022 22:41:50 -0500 Subject: [PATCH 18/57] update several things - including an Amiga fix --- README.md | 6 +++--- papers/doc/7-systems/README.md | 14 ++++++-------- papers/doc/7-systems/amiga.md | 6 +++--- papers/doc/7-systems/arcade.md | 32 -------------------------------- papers/doc/7-systems/genesis.md | 2 +- papers/doc/7-systems/segapcm.md | 4 ++++ papers/doc/7-systems/sms.md | 11 ++++------- papers/doc/7-systems/ym2151.md | 4 +++- papers/doc/README.md | 2 +- src/engine/sysDef.cpp | 1 + 10 files changed, 26 insertions(+), 56 deletions(-) delete mode 100644 papers/doc/7-systems/arcade.md diff --git a/README.md b/README.md index 116d87714..6c62768a7 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ check out the [Releases](https://github.com/tildearrow/furnace/releases) page. a - bug/quirk implementation for increased playback accuracy through compatibility flags - VGM export - modular layout that you may adapt to your needs -- audio file export - entire song, per system or per channel +- audio file export - entire song, per chip or per channel - quality emulation cores (Nuked, MAME, SameBoy, Mednafen PCE, NSFplay, puNES, reSID, Stella, SAASound, vgsound_emu and ymfm) - wavetable synthesizer - available on wavetable chips @@ -237,7 +237,7 @@ yup, it's real. > where's the manual? -see [papers/](papers/doc/README.md). it's kind of incomplete, but at least the systems (sound chips) section is there. +see [papers/](papers/doc/README.md). it's kind of incomplete, but at least the sound chips section is there. > it doesn't open under macOS! @@ -263,7 +263,7 @@ also provided are two effects: - `4xxx`: set fine cutoff. `xxx` range is 000-7ff. additionally, you can change the cutoff and/or duty as a macro inside an instrument by clicking the `absolute cutoff macro` and/or `absolute duty macro` checkbox at the bottom of the instrument. (for the filter, you also need to click the checkbox that says `volume macro is cutoff macro`.) -> how do I use PCM on a PCM-capable system? +> how do I use PCM on a PCM-capable chip? two possibilities: - the recommended way is by creating the "Sample" type instrument and assigning a sample to it. diff --git a/papers/doc/7-systems/README.md b/papers/doc/7-systems/README.md index 080e72690..1fd01c96c 100644 --- a/papers/doc/7-systems/README.md +++ b/papers/doc/7-systems/README.md @@ -1,22 +1,20 @@ -# systems +# sound chips -this is a list of systems that Furnace supports, including each system's effects. +this is a list of sound chips that Furnace supports, including each system's effects. -- [Sega Genesis/Mega Drive](genesis.md) -- [Sega Master System](sms.md) +- [Yamaha YM2612](ym2612.md) +- [TI SN76489](sms.md) - [Yamaha OPLL](opll.md) - [Game Boy](game-boy.md) - [PC Engine/TurboGrafx-16](pce.md) - [NES](nes.md) - [Commodore 64](c64.md) -- [Arcade (YM2151/PCM)](arcade.md) +- [Yamaha YM2151](ym2151.md) +- [SegaPCM](segapcm.md) - [Neo Geo/YM2610](ym2610.md) - [Taito Arcade/YM2610B](ym2610b.md) - [AY-3-8910](ay8910.md) - [Amiga](amiga.md) -- [Yamaha YM2612 standalone](ym2612.md) -- [Yamaha YM2151 standalone](ym2151.md) -- [SegaPCM](segapcm.md) - [Capcom QSound](qsound.md) - [Atari 2600](tia.md) - [Philips SAA1099](saa1099.md) diff --git a/papers/doc/7-systems/amiga.md b/papers/doc/7-systems/amiga.md index cbc73f7ae..419114450 100644 --- a/papers/doc/7-systems/amiga.md +++ b/papers/doc/7-systems/amiga.md @@ -6,10 +6,10 @@ in this very computer music trackers were born... # effects -- `10xx`: change wave. - - only works when "Mode" is set to "Wavetable" in the instrument. +- `10xx`: toggle low-pass filter. `0` turns it off and `1` turns it on. - `11xx`: toggle amplitude modulation with the next channel. - does not work on the last channel. - `12xx`: toggle period (frequency) modulation with the next channel. - does not work on the last channel. -- `13xx`: toggle low-pass filter. `0` turns it off and `1` turns it on. \ No newline at end of file +- `13xx`: change wave. + - only works when "Mode" is set to "Wavetable" in the instrument. diff --git a/papers/doc/7-systems/arcade.md b/papers/doc/7-systems/arcade.md deleted file mode 100644 index dc9496e6b..000000000 --- a/papers/doc/7-systems/arcade.md +++ /dev/null @@ -1,32 +0,0 @@ -# Arcade (Yamaha YM2151/PCM) - -this chip combination was used in the Sega OutRun, X and Y arcade boards, and perhaps a few others. -the actual PCM chip had 16 channels, but the number has been cut to 5 in DefleMask for seemingly arbitrary reasons. - -# effects - -- `10xx`: set noise frequency of channel 8 operator 4. 00 disables noise while 01 to 20 enables it. -- `11xx`: set feedback of channel. -- `12xx`: set operator 1 level. -- `13xx`: set operator 2 level. -- `14xx`: set operator 3 level. -- `15xx`: set operator 4 level. -- `16xy`: set multiplier of operator. - - `x` is the operator (1-4). - - `y` is the mutliplier. -- `17xx`: set LFO speed. -- `18xx`: set LFO waveform. `xx` may be one of the following: - - `00`: saw - - `01`: square - - `02`: triangle - - `03`: noise -- `19xx`: set attack of all operators. -- `1Axx`: set attack of operator 1. -- `1Bxx`: set attack of operator 2. -- `1Cxx`: set attack of operator 3. -- `1Dxx`: set attack of operator 4. -- `1Exx`: set AM depth. -- `1Fxx`: set PM depth. -- `20xx`: set PCM frequency. - - only works on the PCM channels. - - `xx` is a 256th fraction of 31250Hz. diff --git a/papers/doc/7-systems/genesis.md b/papers/doc/7-systems/genesis.md index 13ce5ab95..3350a6eae 100644 --- a/papers/doc/7-systems/genesis.md +++ b/papers/doc/7-systems/genesis.md @@ -2,7 +2,7 @@ a video game console that showed itself as the first true rival to Nintendo's video game market near-monopoly in the US during the '80's. -this console is powered by two sound chips: the Yamaha YM2612 and a derivative of the SN76489. +this console is powered by two sound chips: the [Yamaha YM2612](ym2612.md) and [a derivative of the SN76489](sms.md). # effects diff --git a/papers/doc/7-systems/segapcm.md b/papers/doc/7-systems/segapcm.md index 364626332..7bd45f5b9 100644 --- a/papers/doc/7-systems/segapcm.md +++ b/papers/doc/7-systems/segapcm.md @@ -6,6 +6,10 @@ yep, that's right! 16 channels of PCM! a chip used in the Sega OutRun/X/Y arcade boards. eventually the MultiPCM surpassed it with 28 channels, and later they joined the software mixing gang. +# 5-channel SegaPCM + +Furnace also has a five channel version of this chip, but it only exists for DefleMask compatibility reasons (which doesn't expose the other channels for rather arbitrary reasons). + # effects - `20xx`: set PCM frequency. - `xx` is a 256th fraction of 31250Hz. diff --git a/papers/doc/7-systems/sms.md b/papers/doc/7-systems/sms.md index 882085f16..86e045396 100644 --- a/papers/doc/7-systems/sms.md +++ b/papers/doc/7-systems/sms.md @@ -1,13 +1,10 @@ -# Sega Master System +# TI SN76489 (e.g. Sega Master System) -the predecessor to Genesis. +a relatively simple sound chip made by Texas Instruments. a derivative of it is used in Sega's Master System, the predecessor to Genesis. -surely had better graphics than NES, but its sound (fairly weak, 4ch PSG with A-3 is a lowest tone) is subject of several jokes. - -this console is powered by a derivative of the Texas Instruments SN76489. - -the original iteration of the SN76489 used in the TI-99/4A computers was clocked much lower at 447 kHz, being able to play as low as 13.670 Hz (A -1). consequentially, pitch accuracy for higher notes is compromised. +the original iteration of the SN76489 used in the TI-99/4A computers was clocked at 447 KHz, being able to play as low as 13.670 Hz (A -1). consequentially, pitch accuracy for higher notes is compromised. +on the other hand, the chip was clocked at a much higher speed on Master System and Genesis, which makes it rather poor in the bass range. # effects diff --git a/papers/doc/7-systems/ym2151.md b/papers/doc/7-systems/ym2151.md index 2291088e1..854a370c9 100644 --- a/papers/doc/7-systems/ym2151.md +++ b/papers/doc/7-systems/ym2151.md @@ -4,6 +4,8 @@ the sound chip powering several arcade boards and the Sharp X1/X68000. Eight 4-o it also was present on several pinball machines and synthesizers of the era, and later surpassed by the YM2414 (OPZ) present in the world-famous TX81Z. +in most arcade boards the chip was used in combination with a PCM chip, like [SegaPCM](segapcm.md) or OKI's line of [ADPCM](msm6258.md) [chips](msm6295.md). + # effects - `10xx`: set noise frequency of channel 8 operator 4. 00 disables noise while 01 to 20 enables it. @@ -63,4 +65,4 @@ it also was present on several pinball machines and synthesizers of the era, and - `5Cxx`: set D2R/SR of operator 1. - `5Dxx`: set D2R/SR of operator 2. - `5Exx`: set D2R/SR of operator 3. -- `5Fxx`: set D2R/SR of operator 4. \ No newline at end of file +- `5Fxx`: set D2R/SR of operator 4. diff --git a/papers/doc/README.md b/papers/doc/README.md index 771ea5f17..2bcf6700f 100644 --- a/papers/doc/README.md +++ b/papers/doc/README.md @@ -8,7 +8,7 @@ this documentation is a work in progress! expect several sections to be incomple 4. [instruments](4-instrument/README.md) 5. [wavetables](5-wave/README.md) 6. [samples](6-sample/README.md) -7. [list of systems](7-systems/README.md) +7. [list of sound chips](7-systems/README.md) # attribution diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index c0006061c..404f64057 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -788,6 +788,7 @@ void DivEngine::registerSystems() { {0x10, {DIV_CMD_AMIGA_FILTER, "10xx: Toggle filter (0 disables; 1 enables)"}}, {0x11, {DIV_CMD_AMIGA_AM, "11xx: Toggle AM with next channel"}}, {0x12, {DIV_CMD_AMIGA_PM, "12xx: Toggle period modulation with next channel"}}, + {0x13, {DIV_CMD_WAVE, "13xx: Set waveform"}} } ); From d5692318d6ae150b72677a990eb41db95b88d3f0 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 00:53:05 -0500 Subject: [PATCH 19/57] lots of doc updates --- papers/doc/1-intro/README.md | 2 +- papers/doc/3-pattern/effects.md | 12 +-- papers/doc/4-instrument/README.md | 2 +- papers/doc/5-wave/README.md | 2 +- papers/doc/7-systems/README.md | 2 +- papers/doc/7-systems/ay8910.md | 6 +- papers/doc/7-systems/ay8930.md | 2 +- papers/doc/7-systems/bubblesystem.md | 2 +- papers/doc/7-systems/c64.md | 4 +- papers/doc/7-systems/dac.md | 4 +- papers/doc/7-systems/fds.md | 1 + papers/doc/7-systems/genesis.md | 3 +- papers/doc/7-systems/lynx.md | 26 +++---- papers/doc/7-systems/msm5232.md | 26 +++++++ papers/doc/7-systems/msm6258.md | 7 ++ papers/doc/7-systems/msm6295.md | 7 ++ papers/doc/7-systems/n163.md | 33 ++++---- papers/doc/7-systems/namco.md | 11 +-- papers/doc/7-systems/nes.md | 4 +- papers/doc/7-systems/oki.md | 9 --- papers/doc/7-systems/opl.md | 2 +- papers/doc/7-systems/opll.md | 2 +- papers/doc/7-systems/pce.md | 1 + papers/doc/7-systems/pcspkr.md | 4 +- papers/doc/7-systems/qsound.md | 10 +-- papers/doc/7-systems/ricoh.md | 2 +- papers/doc/7-systems/saa1099.md | 5 +- papers/doc/7-systems/segapcm.md | 1 + papers/doc/7-systems/snes.md | 111 +++++++++++++++++---------- papers/doc/7-systems/soundunit.md | 13 +++- papers/doc/7-systems/vic20.md | 15 +++- papers/doc/7-systems/vrc6.md | 4 +- papers/doc/7-systems/wonderswan.md | 8 +- papers/doc/7-systems/ym2151.md | 2 +- papers/doc/7-systems/ym2203.md | 2 +- papers/doc/7-systems/ym2608.md | 2 +- papers/doc/7-systems/ym2610.md | 4 +- papers/doc/7-systems/ym2610b.md | 2 +- papers/doc/7-systems/ym2612.md | 2 +- papers/doc/7-systems/ymz280b.md | 4 +- papers/doc/7-systems/zxbeep.md | 8 +- 41 files changed, 229 insertions(+), 140 deletions(-) create mode 100644 papers/doc/7-systems/msm5232.md create mode 100644 papers/doc/7-systems/msm6258.md create mode 100644 papers/doc/7-systems/msm6295.md delete mode 100644 papers/doc/7-systems/oki.md diff --git a/papers/doc/1-intro/README.md b/papers/doc/1-intro/README.md index 41cb32dc0..a550aca1f 100644 --- a/papers/doc/1-intro/README.md +++ b/papers/doc/1-intro/README.md @@ -1,7 +1,7 @@ # introduction Furnace is a tool which allows you to create music using emulated sound chips from the 8/16-bit era. -For a full list of soundchips that Furnace supports, please see [the list of systems](https://github.com/tildearrow/furnace/tree/master/papers/doc/7-systems). +For a full list of soundchips that Furnace supports, please see [this list](https://github.com/tildearrow/furnace/tree/master/papers/doc/7-systems). It has a music tracker interface. think of a piano roll, or a table that scrolls up and plays the notes. diff --git a/papers/doc/3-pattern/effects.md b/papers/doc/3-pattern/effects.md index f72be5013..1fa4755bb 100644 --- a/papers/doc/3-pattern/effects.md +++ b/papers/doc/3-pattern/effects.md @@ -13,16 +13,16 @@ however, effects are continuous, which means you only need to type it once and t - `07xy`: tremolo. `x` is the speed, while `y` is the depth. - maximum tremolo depth is -60 volume steps. - `08xy`: set panning. `x` is the left channel and `y` is the right one. - - not all systems support this effect. + - not all chips support this effect. - `80xx`: set panning (linear). this effect behaves more like other trackers: - `00` is left. - `80` is center. - `FF` is right. - - not all systems support this effect. + - not all chips support this effect. - `81xx`: set volume of left channel (from `00` to `FF`). - - not all systems support this effect. + - not all chips support this effect. - `82xx`: set volume of right channel (from `00` to `FF`). - - not all systems support this effect. + - not all chips support this effect. - `09xx`: set speed 1. - `0Axy`: volume slide. - if `x` is 0 then this is a slide down. @@ -34,7 +34,7 @@ however, effects are continuous, which means you only need to type it once and t - `0Fxx`: set speed 2. - `9xxx`: set sample position to `xxx`\*0x100. - - not all systems support this effect. + - not all chips support this effect. - `Cxxx`: change song Hz. - `xxx` may be from `000` to `3ff`. @@ -72,4 +72,4 @@ however, effects are continuous, which means you only need to type it once and t - if `y` is 0 then this is a slide up. - `FFxx`: end of song/stop playback. -additionally each system has its own effects. [click here for more details](../7-systems/README.md). +additionally each chip has its own effects. [click here for more details](../7-systems/README.md). diff --git a/papers/doc/4-instrument/README.md b/papers/doc/4-instrument/README.md index 1ffff7e54..58d7bac9d 100644 --- a/papers/doc/4-instrument/README.md +++ b/papers/doc/4-instrument/README.md @@ -20,7 +20,7 @@ depending on the instrument type, there are currently 13 different types of an i - [AY8930](8930.md) - for use with Microchip AY8930 E-PSG sound source. - [Commodore 64](c64.md) - for use with Commodore 64 SID. - [SAA1099](saa.md) - for use with Philips SAA1099 PSG sound source. -- [TIA](tia.md) - for use with Atari 2600 system. +- [TIA](tia.md) - for use with Atari 2600 chip. - [AY-3-8910](ay8910.md) - for use with AY-3-8910 PSG sound source and SSG portion in YM2610. - [Amiga/sample](amiga.md) for controlling Amiga and other sample based synthsizers like YM2612's Channel 6 PCM mode, NES channel 5, Sega PCM, X1-010 and PC Engine's sample playback mode. - [Atari Lynx](lynx.md) - for use with Atari Lynx handheld console. diff --git a/papers/doc/5-wave/README.md b/papers/doc/5-wave/README.md index b22e86992..e04834cc9 100644 --- a/papers/doc/5-wave/README.md +++ b/papers/doc/5-wave/README.md @@ -2,7 +2,7 @@ Wavetable synthesizers, in context of Furnace, are sound sources that operate on extremely short n-bit PCM streams. By extremely short, no more than 256 bytes. This amount of space is nowhere near enough to store an actual sampled sound, it allows certain amount of freedom to define a waveform shape. As of Furnace 0.5.8, wavetable editor affects PC Engine, WonderSwan and channel 3 of Game Boy. -Furnace's wavetable editor is rather simple, you can draw the waveform using mouse or by pasting an MML bit stream in the input field. Maximum wave width (length) is 256 bytes, and maximum wave height (depth) is 256. NOTE: Game Boy, PCE, WonderSwan and Bubble System can handle max 32 byte waveforms, X1-010 can handle max 128 byte waveforms as of now, with 16-level height for GB, X1-010 Envelope, WS, Bubble System and N163, and 32-level height for PCE. If a larger wave is defined for these systems, it will be squashed to fit within the constraints of the system. +Furnace's wavetable editor is rather simple, you can draw the waveform using mouse or by pasting an MML bit stream in the input field. Maximum wave width (length) is 256 bytes, and maximum wave height (depth) is 256. NOTE: Game Boy, PCE, WonderSwan and Bubble System can handle max 32 byte waveforms, X1-010 can handle max 128 byte waveforms as of now, with 16-level height for GB, X1-010 Envelope, WS, Bubble System and N163, and 32-level height for PCE. If a larger wave is defined for these chips, it will be squashed to fit within the constraints of the chips. ## wavetable synthesizer diff --git a/papers/doc/7-systems/README.md b/papers/doc/7-systems/README.md index 1fd01c96c..5ebe97362 100644 --- a/papers/doc/7-systems/README.md +++ b/papers/doc/7-systems/README.md @@ -1,6 +1,6 @@ # sound chips -this is a list of sound chips that Furnace supports, including each system's effects. +this is a list of sound chips that Furnace supports, including effects. - [Yamaha YM2612](ym2612.md) - [TI SN76489](sms.md) diff --git a/papers/doc/7-systems/ay8910.md b/papers/doc/7-systems/ay8910.md index 5df69eb65..25eb77f7e 100644 --- a/papers/doc/7-systems/ay8910.md +++ b/papers/doc/7-systems/ay8910.md @@ -2,9 +2,9 @@ this chip was used in many home computers (ZX Spectrum, MSX, Amstrad CPC, Atari ST, etc.), video game consoles (Intellivision and Vectrex), arcade boards and even slot machines! -It is a 3-channel PSG sound source. The chip's powerful sound comes from the envelope... +it is a 3-channel square/noise/envelope sound generator. the chip's powerful sound comes from the envelope... -AY-3-8914 variant was used in Intellivision, it's basically original AY with 4 level envelope volume per channel and different register format. +the AY-3-8914 variant was used in Intellivision, which is pretty much an AY with 4 level envelope volume per channel and different register format. # effects @@ -43,4 +43,4 @@ AY-3-8914 variant was used in Intellivision, it's basically original AY with 4 l - `2Exx`: write to I/O port A. - this changes the port's mode to "write". make sure you have connected something to it. - `2Fxx`: write to I/O port B. - - this changes the port's mode to "write". make sure you have connected something to it. \ No newline at end of file + - this changes the port's mode to "write". make sure you have connected something to it. diff --git a/papers/doc/7-systems/ay8930.md b/papers/doc/7-systems/ay8930.md index 6d9db10a9..6d5200cac 100644 --- a/papers/doc/7-systems/ay8930.md +++ b/papers/doc/7-systems/ay8930.md @@ -5,7 +5,7 @@ a backwards-compatible successor to the AY-3-8910, with increased volume resolut sadly, this soundchip has only ever observed minimal success, and has remained rather obscure since. it is known for being used in the Covox Sound Master, which didn't sell well either. -while emulation of this chip is mostly complete, hardware comparison hasn't been performed yet due to its scarcity. it also was emulated in a now-abandoned tracker with similar goal as Furnace, which sparked interest on the chip. +emulation of this chip in Furnace is now complete thanks to community efforts and hardware testing, which an MSX board called Darky has permitted. # effects diff --git a/papers/doc/7-systems/bubblesystem.md b/papers/doc/7-systems/bubblesystem.md index 7b14e90ea..b339b893e 100644 --- a/papers/doc/7-systems/bubblesystem.md +++ b/papers/doc/7-systems/bubblesystem.md @@ -6,7 +6,7 @@ however, the K005289 is just part of the logic used for pitch and wavetable ROM waveform select and volume control are tied with single AY-3-8910 IO for both channels. another AY-3-8910 IO is used for reading sound hardware status. -Furnace emulates this configuration as single system with 32x16 wavetables. +Furnace emulates this configuration as a "chip" with 32x16 wavetables. # effects diff --git a/papers/doc/7-systems/c64.md b/papers/doc/7-systems/c64.md index 9b3e87013..0f8054efa 100644 --- a/papers/doc/7-systems/c64.md +++ b/papers/doc/7-systems/c64.md @@ -1,10 +1,10 @@ # Commodore 64 -a home computer with a synthesizer-grade sound chip of which people took decades to master. Three oscillators with four selectable waveforms, ring modulation, oscillator sync, multimode filter, ADSR envelope... +a home computer with a synthesizer-grade sound chip of which people took decades to master. three oscillators with four selectable waveforms, ring modulation, oscillator sync, multi-mode filter and ADSR envelope. very popular in Europe and mostly due to the demoscene, which stretched the machine's limbs to no end. -Two revisions do exist - 6581 (original chip) and 8580 (improved version with working waveform mixing and somewhat more consistent filter curves) +two versions of aforementioned chip exist - 6581 (original chip) and 8580 (improved version with working waveform mixing and somewhat more consistent filter curves). # effects diff --git a/papers/doc/7-systems/dac.md b/papers/doc/7-systems/dac.md index 856db2cd0..60bdd96c0 100644 --- a/papers/doc/7-systems/dac.md +++ b/papers/doc/7-systems/dac.md @@ -1,6 +1,8 @@ # Generic PCM DAC -Realtek HD Audio's predecessor. It's just a 1/8/16-bit sample channel, with freely selectable rate and mono/stereo settings. With it, you can emulate PCM DACs found in Williams arcade boards, Sound Blasters, MSX TurboR, Atari STE, NEC PC-9801-86 etc. +a sample channel, with freely selectable rate, mono/stereo and bit depth settings. + +with it, you can emulate PCM DACs found in Williams arcade boards, Sound Blasters, MSX TurboR, Atari STe, NEC PC-9801-86, among others. # effects diff --git a/papers/doc/7-systems/fds.md b/papers/doc/7-systems/fds.md index 1174b3f3b..e7bede281 100644 --- a/papers/doc/7-systems/fds.md +++ b/papers/doc/7-systems/fds.md @@ -24,3 +24,4 @@ it also offers an additional 6-bit, 64-byte wavetable sound channel with (somewh - 5: -3 - 6: -2 - 7: -1 + - why is this mapping so unnatural? because that's how DefleMask does it (yeah, as you may have guessed this effect is mostly for compatibility reasons)... diff --git a/papers/doc/7-systems/genesis.md b/papers/doc/7-systems/genesis.md index 3350a6eae..ceebf88aa 100644 --- a/papers/doc/7-systems/genesis.md +++ b/papers/doc/7-systems/genesis.md @@ -19,9 +19,10 @@ this console is powered by two sound chips: the [Yamaha YM2612](ym2612.md) and [ - `y` is the mutliplier. - `17xx`: enable PCM channel. - this only works on channel 6. + - **this effect is there for compatibility reasons** - it is otherwise recommended to use Sample type instruments (which automatically enable PCM mode when used). - `18xx`: toggle extended channel 3 mode. - 0 disables it and 1 enables it. - - only in extended channel 3 system. + - only in extended channel 3 chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/lynx.md b/papers/doc/7-systems/lynx.md index a92b25806..e7178a611 100644 --- a/papers/doc/7-systems/lynx.md +++ b/papers/doc/7-systems/lynx.md @@ -1,22 +1,20 @@ # Atari Lynx/MIKEY -The Atari Lynx is a 16 bit handheld console developed by (obviously) Atari Corporation, and initially released in September of 1989, with the worldwide release being in 1990. +the Atari Lynx is a 16 bit handheld console developed by (obviously) Atari Corporation, and initially released in September of 1989, with the worldwide release being in 1990. -The Lynx, while being an incredible handheld for the time (and a lot more powerful than a Game Boy), unfortunately meant nothing in the end due to the Lynx being a market failure, and ending up as one of the things that contributed to the downfall of Atari. +while it was an incredible handheld for the time (and a lot more powerful than a Game Boy), it unfortunately meant nothing in the end due to the Lynx being a market failure, and ending up as one of the things that contributed to the downfall of Atari. -Although the Lynx is still getting (rather impressive) homebrew developed for it, it does not mean that the Lynx is a popular system at all. +although the Lynx is still getting (rather impressive) homebrew developed for it, that does not mean the Lynx is a popular system at all. -The Atari Lynx's custom sound chip and CPU (MIKEY) is a 6502-based 8 bit CPU running at 16MHz, however this information is generally not useful in the context of Furnace. +the Atari Lynx has a 6502-based CPU with a sound part (this chip is known as MIKEY). it has the following sound capabilities: +- 4 channels of LFSR-based sound, which can be modulated with different frequencies (×0, ×1, ×2, ×3, ×4, ×5, ×7, ×10, and ×11) to create square waves and wavetable-like results. + - likewise, when a lot of the modulators are activated, this can provide a "pseudo-white noise"-like effect, which can be useful for drums and sound effects. +- hard stereo panning capabilities via the `08xx` effect command. +- four 8-bit DACs (Digital to Analog Converter), one for each voice. this allows for sample playback (at the cost of CPU time and memory). +- a variety of pitches to choose from, and they go from 32Hz to "above the range of human hearing", according to Atari. -## Sound capabilities +# effects - - The MIKEY has 4 channels of square wave-based sound, which can be modulated with different frequencies (×0, ×1, ×2, ×3, ×4, ×5, ×7, ×10, and ×11) to create wavetable-like results. - - Likewise, when a lot of the modulators are activated, this can provide a "pseudo-white noise"-like effect, whoch can be useful for drums and sound effects. - - The MIKEY also has hard stereo panning capabilities via the `08xx` effect command. - - The MIKEY has four 8-bit DACs (Digital to Analog Converter) — one for each voice — that essentially mean you can play samples on the MIKEY (at the cost of CPU time and memory). - - The MIKEY also has a variety of pitches to choose from, and they go from 32Hz to "above the range of human hearing", according to Atari. - -## Effect commands - - `3xxx`: Load LFSR (0 to FFF). +- `3xxx`: Load LFSR (0 to FFF). - this is a bitmask. - - for it to work, duty macro in instrument editor must be set to some value, without it LFSR will not be fed with any bits. + - for it to work, duty macro in instrument editor must be set to some value. without it LFSR will not be fed with any bits. diff --git a/papers/doc/7-systems/msm5232.md b/papers/doc/7-systems/msm5232.md new file mode 100644 index 000000000..b08875a3b --- /dev/null +++ b/papers/doc/7-systems/msm5232.md @@ -0,0 +1,26 @@ +# OKI MSM5232 + +a rather primitive (but powerful) sound generator chip used in some arcade boards and even synthesizers (like Korg Poly-800). + +it has 8 channels in 2 groups (of 4 channels each). each group can be configured with an envelope and the ability to produce 2', 4', 8' and/or 16' square/noise overtones on 8 outputs (four (2', 4', 8' and 16') per group). + +however, this chip cannot entirely produce sound alone. it has to be paired with either an external envelope generator or capacitors to assist the internal envelope generator. + +it also has no fine tune whatsoever. the frequency resolution is exactly a semitone. + +Furnace implements this chip in a way that allows the following features: +- internal (capacitors) or external (volume macro) envelope modes per group +- the ability to change the volume of each output (this can be used to generate saw waves if you set each part/overtone's volume to exactly half of the previous one) +- global fine tune +- global vibrato (some arcade boards played with the clock input to simulate vibrato) + +# effects + +- `10xy`: set group control. + - `x` sets sustain mode. + - `y` is a 4-bit mask which toggles overtones. +- `11xx`: set noise mode. +- `12xx`: set group attack (0 to 5). + - only in internal (capacitor-based) envelope mode. +- `13xx`: set group decay (0 to 11). + - only in internal (capacitor-based) envelope mode. diff --git a/papers/doc/7-systems/msm6258.md b/papers/doc/7-systems/msm6258.md new file mode 100644 index 000000000..a71aa9507 --- /dev/null +++ b/papers/doc/7-systems/msm6258.md @@ -0,0 +1,7 @@ +# OKI MSM6258 + +a single-channel ADPCM sound source developed by OKI. it allows max sample rate of 15.6 KHz... with no variable pitch. most prominent use of this chip was Sharp X68000 computer, where it was paired with Yamaha YM2151. + +# effects + +... diff --git a/papers/doc/7-systems/msm6295.md b/papers/doc/7-systems/msm6295.md new file mode 100644 index 000000000..257669277 --- /dev/null +++ b/papers/doc/7-systems/msm6295.md @@ -0,0 +1,7 @@ +# OKI MSM6295 + +an upgrade from 6258 - it provides 4 ADPCM channels, at max 32 KHz (still no variable pitch though). between late 80s and late 90s, it was one of the most common, if not THE most common soundchip used in arcade machines (Capcom, Toaplan, Kaneko, Atari, Tecmo, the list can go on and on...) + +# effects + +- `20xx`: set chip output rate. diff --git a/papers/doc/7-systems/n163.md b/papers/doc/7-systems/n163.md index efdc3c506..06f2d0b1f 100644 --- a/papers/doc/7-systems/n163.md +++ b/papers/doc/7-systems/n163.md @@ -1,25 +1,32 @@ # Namco 163 (also called N163, Namco C163, Namco 106 (sic), Namco 160 or Namco 129) -This is one of Namco's NES mappers, with up to 8 wavetable channels. It has also 256 nibbles (128 bytes) of internal RAM, and both channel registers and wavetables are stored here. Wavetables are variable in size and freely allocable anywhere in RAM, it means it can use part of or continuously pre-loaded waveform and its sequences in RAM. At least 128 nibbles (64 bytes) can be dedicated to waves, with more available if not all channels are used - waveform RAM area becomes smaller as more channels are activated, since channel registers consume 8 bytes for each channel. You must avoid conflict with channel register area and waveform to avoid broken channel playback. +this is one of Namco's NES mappers, with up to 8 wavetable channels. + +it has 256 nibbles (128 bytes) of internal RAM which is shared between channel state and waves. + +wavetables are variable in size and may be allocated anywhere in RAM. at least 128 nibbles (64 bytes) can be dedicated to waves, with more available if not all channels are used - waveform RAM area becomes smaller as more channels are activated, since channel registers consume 8 bytes for each channel. Namco 163 uses time-division multiplexing for its output. this means that only one channel is output per sample (like OPLL and OPN2). therefore, its sound quality gets worse as more channels are activated. Furnace supports loading waveforms into RAM and waveform playback simultaneously, and channel limit is dynamically changeable with effect commands. -You must load waveform to RAM first for playback, as its load behavior auto-updates when every waveform changes. -Both waveform playback and load command works independently per each channel columns, (Global) commands don't care about the channel columns for work commands and its load behavior is independent with per-channel column load commands. + +you must load waveform to RAM first for playback, as its load behavior auto-updates when every waveform changes. + +both waveform playback and load command work independently per each channel columns. +(Global) commands don't care about the channel columns for work commands and its load behavior is independent with per-channel column load commands. # effects - `10xx`: set waveform for playback. -- `11xx`: set waveform position in RAM for playback. (single nibble unit) -- `12xx`: set waveform length in RAM for playback. (04 to FC, 4 nibble unit) -- `130x`: set playback waveform update behavior. (0: off, bit 0: update now, bit 1: update when every waveform is changed) +- `11xx`: set waveform position in RAM for playback (single nibble unit). +- `12xx`: set waveform length in RAM for playback (04 to FC, 4 nibble unit). +- `130x`: set playback waveform update behavior (0: off, bit 0: update now, bit 1: update when every waveform is changed). - `14xx`: set waveform for load to RAM. -- `15xx`: set waveform position for load to RAM. (single nibble unit) -- `16xx`: set waveform length for load to RAM. (04 to FC, 4 nibble unit) -- `170x`: set waveform load behavior. (0: off, bit 0: load now, bit 1: load when every waveform is changed) -- `180x`: set channel limit (0 to 7, x + 1) +- `15xx`: set waveform position for load to RAM (single nibble unit). +- `16xx`: set waveform length for load to RAM (04 to FC, 4 nibble unit). +- `170x`: set waveform load behavior (0: off, bit 0: load now, bit 1: load when every waveform is changed). +- `180x`: set channel limit (0 to 7, x + 1). - `20xx`: (Global) set waveform for load to RAM. -- `21xx`: (Global) set waveform position for load to RAM. (single nibble unit) -- `22xx`: (Global) set waveform length for load to RAM. (04 to FC, 4 nibble unit) -- `230x`: (Global) set waveform load behavior. (0: off, bit 0: load now, bit 1: load when every waveform is changed) +- `21xx`: (Global) set waveform position for load to RAM (single nibble unit). +- `22xx`: (Global) set waveform length for load to RAM (04 to FC, 4 nibble unit). +- `230x`: (Global) set waveform load behavior (0: off, bit 0: load now, bit 1: load when every waveform is changed). diff --git a/papers/doc/7-systems/namco.md b/papers/doc/7-systems/namco.md index a856d8fb5..0a53d15d7 100644 --- a/papers/doc/7-systems/namco.md +++ b/papers/doc/7-systems/namco.md @@ -1,13 +1,10 @@ # Namco WSG | Namco C15 | Namco C30 -a family of wavetable synth sound chips used by Namco in their arcade machines (Pacman and later). Waveforms are 4-bit, with 32-byte sample length. +a family of wavetable synth sound chips used by Namco in their arcade machines (Pacman and later). waveforms are 4-bit, with 32-byte sample length. -Everything starts with Namco WSG, simple 3ch wavetable with no extra frills. C15 is much more advanced sound source with 8 channels. C30 adds stereo output and noise mode. +everything starts with Namco WSG, which is a simple 3-channel wavetable with no extra frills. C15 is a much more advanced sound source with 8 channels, and C30 adds stereo output and noise mode. # effects --`10xx`: change waveform --`11xx`: toggle noise mode WARNING: only on C30 - - - +- `10xx`: change waveform. +- `11xx`: toggle noise mode (WARNING: only on C30). diff --git a/papers/doc/7-systems/nes.md b/papers/doc/7-systems/nes.md index 3ccca2647..c9b4d0242 100644 --- a/papers/doc/7-systems/nes.md +++ b/papers/doc/7-systems/nes.md @@ -2,7 +2,7 @@ the console from Nintendo that plays Super Mario Bros. and helped revive the agonizing video game market in the US during mid-80s. -also known as Famicom. It is a five-channel PSG: first two channels play pulse wave with three different duty cycles, third is a fixed-volume triangle channel, fourth is a noise channel (can work in both pseudo-random and periodic modes) and fifth is a (D)PCM sample channel. +also known as Famicom. it is a five-channel sound generator: first two channels play pulse wave with three different duty cycles, third is a fixed-volume triangle channel, fourth is a noise channel (can work in both pseudo-random and periodic modes) and fifth is a (D)PCM sample channel. # effects @@ -22,4 +22,4 @@ also known as Famicom. It is a five-channel PSG: first two channels play pulse w - `18xx`: set PCM channel mode. - `00`: PCM (software). - `01`: DPCM (hardware). - - when in DPCM mode, samples will sound muffled (due to its nature), availables pitches are limited and loop point is ignored. \ No newline at end of file + - when in DPCM mode, samples will sound muffled (due to its nature), availables pitches are limited and loop point is ignored. diff --git a/papers/doc/7-systems/oki.md b/papers/doc/7-systems/oki.md deleted file mode 100644 index 4b46eb21c..000000000 --- a/papers/doc/7-systems/oki.md +++ /dev/null @@ -1,9 +0,0 @@ -# OKI MSM6258 | OKI MSM6295 - -MSM6258 is a single-channel ADPCM sound source developed by OKI. It allows max sample rate of 15.6 kHz... with no variable pitch. Most prominent use of this chip was Sharp X68000 computer, where it was paired with Yamaha YM2151. - -MSM6295 is an upgrade from 6258 - it provides 4 ADPCM channels, at max 32 kHz (still no variable pitch though). Between late 80s and late 90s, it was one of the most common, if not THE most common soundchip used in arcade machines (Capcom, Toaplan, Kaneko, Atari, Tecmo, the list can go on and on...) - -# effects - -- `20xx`: set chip output rate diff --git a/papers/doc/7-systems/opl.md b/papers/doc/7-systems/opl.md index 683be51e6..33bf627e5 100644 --- a/papers/doc/7-systems/opl.md +++ b/papers/doc/7-systems/opl.md @@ -36,7 +36,7 @@ afterwards everyone moved to Windows and software mixed PCM streaming... - this effect applies to all channels. - `18xx`: toggle drums mode. - 0 disables it and 1 enables it. - - only in drums system. + - only in drums chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/opll.md b/papers/doc/7-systems/opll.md index d0e6475c7..0f9c0f9d8 100644 --- a/papers/doc/7-systems/opll.md +++ b/papers/doc/7-systems/opll.md @@ -33,7 +33,7 @@ the YM2413 is equipped with the following features: - `y` is the mutliplier. - `18xx`: toggle drums mode. - 0 disables it and 1 enables it. - - only in drums system. + - only in drums chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/pce.md b/papers/doc/7-systems/pce.md index c061a9b7a..2405ac4f6 100644 --- a/papers/doc/7-systems/pce.md +++ b/papers/doc/7-systems/pce.md @@ -19,3 +19,4 @@ furthermore, it has some PCM and LFO! - when LFO is enabled, channel 2 is muted and its output is passed to channel 1's frequency. - `13xx`: set LFO speed. - `17xx`: toggle PCM mode. + - **this effect is there for compatibility reasons** - it is otherwise recommended to use Sample type instruments (which automatically enable PCM mode when used). diff --git a/papers/doc/7-systems/pcspkr.md b/papers/doc/7-systems/pcspkr.md index 50940a5a7..a6a55ba65 100644 --- a/papers/doc/7-systems/pcspkr.md +++ b/papers/doc/7-systems/pcspkr.md @@ -4,8 +4,8 @@ # real output -so far this is the only system in Furnace which has a real hardware output option. -to enable it, select file > configure system... > PC Speaker > Use system beeper. +so far this is the only chip in Furnace which has a real hardware output option. +to enable it, select file > configure chip... > PC Speaker > Use system beeper. be noted that this will only work on Linux as Windows does not provide any user-space APIs to address the PC speaker directly! diff --git a/papers/doc/7-systems/qsound.md b/papers/doc/7-systems/qsound.md index 5d6078aa7..7089ec0e8 100644 --- a/papers/doc/7-systems/qsound.md +++ b/papers/doc/7-systems/qsound.md @@ -1,14 +1,14 @@ # Capcom QSound (DL-1425) -This chip was used in Capcom's CP System Dash, CP System II and ZN arcade PCBs. +this chip was used in Capcom's CP System Dash, CP System II and ZN arcade PCBs. -It supports 16 PCM channels and uses the patented (now expired) QSound stereo expansion algorithm, as the name implies. +it supports 16 PCM channels and uses the patented (now expired) QSound stereo expansion algorithm, as the name implies. -Because the chip lacks sample interpolation, it's recommended that you try to play samples at around 24038 Hz to avoid aliasing. This is especially important for e.g. cymbals. +because the chip lacks sample interpolation, it is recommended that you try to play samples at around 24038 Hz to avoid aliasing. this is especially important for e.g. cymbals. -The QSound chip also has a small echo buffer, somewhat similar to the SNES, although with a very basic (and non-adjustable) filter. It is however possible to adjust the feedback and length of the echo buffer. The initial values can be set in the "Configure system" dialog. +the QSound chip also has a small echo buffer, somewhat similar to the SNES, although with a very basic (and non-adjustable) filter. it is however possible to adjust the feedback and length of the echo buffer (the initial values can be set in the "configure chip" option in the file menu or the chip manager). -There are also 3 ADPCM channels, however they cannot be used in Furnace yet. They have been reserved in case this feature is added later. ADPCM samples are limited to 8012 Hz. +there are also 3 ADPCM channels, however they cannot be used in Furnace yet. they have been reserved in case this feature is added later. ADPCM samples are limited to 8012 Hz. # effects diff --git a/papers/doc/7-systems/ricoh.md b/papers/doc/7-systems/ricoh.md index 6f5405f2b..518326022 100644 --- a/papers/doc/7-systems/ricoh.md +++ b/papers/doc/7-systems/ricoh.md @@ -1,6 +1,6 @@ # Ricoh RF5C68 -YM2612's sidekick - poor man's SPC-700. 8ch PCM sample-based synthesizer used in Sega Mega CD, Fujitsu FM Towns and some of Sega's arcade machines. Supports up to 64 Kbytes of external PCM data. +YM2612's sidekick - poor man's SNES DSP. 8-channel PCM sample-based synthesizer used in Sega CD, Fujitsu FM Towns and some of Sega's arcade machines. supports up to 64KB of external PCM data. # effects diff --git a/papers/doc/7-systems/saa1099.md b/papers/doc/7-systems/saa1099.md index 9cf7b6431..8c58bbbb5 100644 --- a/papers/doc/7-systems/saa1099.md +++ b/papers/doc/7-systems/saa1099.md @@ -1,9 +1,8 @@ # Philips SAA1099 this was used by the Game Blaster and SAM Coupé. it's pretty similar to the AY-3-8910, but has stereo sound, twice the channels and two envelopes, both of which are highly flexible. The envelopes work like this: - -an instrument with envelope settings is placed on channel 2 or channel 5 -an instrument that is used as an "envelope output", is placed on channel 3 or channel 6. You may want to disable wave output on the output channel. +- an instrument with envelope settings is placed on channel 2 or channel 5 +- an instrument that is used as an "envelope output" is placed on channel 3 or channel 6 (you may want to disable wave output on the output channel) # effects diff --git a/papers/doc/7-systems/segapcm.md b/papers/doc/7-systems/segapcm.md index 7bd45f5b9..ba1a81186 100644 --- a/papers/doc/7-systems/segapcm.md +++ b/papers/doc/7-systems/segapcm.md @@ -11,6 +11,7 @@ a chip used in the Sega OutRun/X/Y arcade boards. eventually the MultiPCM surpas Furnace also has a five channel version of this chip, but it only exists for DefleMask compatibility reasons (which doesn't expose the other channels for rather arbitrary reasons). # effects + - `20xx`: set PCM frequency. - `xx` is a 256th fraction of 31250Hz. - this effect exists for mostly DefleMask compatibility - it is otherwise recommended to use Sample type instruments. diff --git a/papers/doc/7-systems/snes.md b/papers/doc/7-systems/snes.md index 25a771265..a2ecd9aee 100644 --- a/papers/doc/7-systems/snes.md +++ b/papers/doc/7-systems/snes.md @@ -1,50 +1,77 @@ -# Super NES +# Super Nintendo Entertainment System (SNES)/Super Famicom -The successor to NES to compete with Genesis. Now packing superior graphics and sample-based audio. Also known as Super Famicom in Japan. +the successor to NES to compete with Genesis, packing superior graphics and sample-based audio. -Its audio subsystem, developed by Sony, features the DSP chip, SPC700 microcontroller and 64KB of dedicated SRAM used by both. This whole system itself is pretty much a separate computer that the main CPU needs to upload its program and samples to. +its audio system, developed by Sony, features a DSP chip, SPC700 CPU and 64KB of dedicated SRAM used by both. +this whole system itself is pretty much a separate computer that the main CPU needs to upload its program and samples to. -Furnace communicates with the DSP directly and provides a full 64KB of memory. This memory might be reduced excessively on ROM export to make up for playback engine and pattern data. As of version 0.6pre2, you can go to `window -> statistics` to see how much memory your samples are using. +Furnace communicates with the DSP directly and provides a full 64KB of memory. this memory might be reduced excessively on ROM export to make up for playback engine and pattern data. you can go to window > statistics to see how much memory your samples are using. -Some notable features of the DSP are: -- It has pitch modulation, meaning that you can use 2 channels to make a basic FM synth without eating up too much memory -- It has a built in noise generator, useful for hihats, cymbals, rides, sfx, among other things. -- It famously features per-channel echo, which unfortunately eats up a lot of memory but can be used to save channels in songs. -- It can loop samples, but the loop points have to be multiples of 16. -- It can invert the left and/or right channels, for surround sound. -- It features ADSR, similar to the Commodore 64, but its functionality is closer to the OPL(L|1|2|3)'s implementation of ADSR. -- It features an 8-tap FIR filter, which is basically a procedural low-pass filter that you can edit however you want. -- 7-bit volume, per-channel. -- Per-channel interpolation, which is basically a low-pass filter that gets affected by the pitch of the channel. +some notable features of the DSP are: +- pitch modulation, meaning that you can use 2 channels to make a basic FM synth without eating up too much memory. +- a built in noise generator, useful for hi-hats, cymbals, rides, effects, among other things. +- per-channel echo, which unfortunately eats up a lot of memory but can be used to save channels in songs. +- an 8-tap FIR filter for the echo, which is basically a procedural low-pass filter that you can edit however you want. +- sample loop, but the loop points have to be multiples of 16. +- left/right channel invert for surround sound. +- ADSR and gain envelope modes. +- 7-bit volume per channel. +- sample interpolation, which is basically a low-pass filter that gets affected by the pitch of the channel. -Furnace also allows the SNES to use wavetables (and the wavetable synthesizer) in order to create more 'animated' sounds, using less memory than regular samples. This, however, is not a hardware feature, and might be difficult to implement on real hardware. +Furnace also allows the SNES to use wavetables (and the wavetable synthesizer) in order to create more 'animated' sounds, using less memory than regular samples. this however is not a hardware feature, and might be difficult to implement on real hardware. # effects -Note: this chip has a signed left/right level. Which can be used for inverted (surround) stereo. A signed 8-bit value means 80 - FF = -128 - -1. Other values work normally. A value of -128 is not recommended as it could cause overflows. - -- `10xx`: Set waveform. -- `11xx`: Toggle noise generator mode. -- `12xx`: Toggle echo on this channel. -- `13xx`: Toggle pitch modulation. -- `14xy`: Toggle inverting the left or right channels. (x: left, y: right) -- `15xx`: Set envelope mode. (0: ADSR, 1: gain/direct, 2: decrement, 3: exponential, 4: increment, 5: bent) -- `16xx`: Set gain. (00 to 7F if direct, 00 to 1F otherwise) -- `18xx`: Enable echo buffer. -- `19xx`: Set echo delay. (0 to F) -- `1Axx`: Set left echo channel volume. -- `1Bxx`: Set right echo channel volume. -- `1Cxx`: Set echo feedback. -- `1Dxx`: Set noise generator frequency. (00 to 1F) -- `20xx`: Set attack (0 to F) -- `21xx`: Set decay (0 to 7) -- `22xx`: Set sustain (0 to 7) -- `23xx`: Set release (00 to 1F) -- `30xx`: Set echo filter coefficient 0 -- `31xx`: Set echo filter coefficient 1 -- `32xx`: Set echo filter coefficient 2 -- `33xx`: Set echo filter coefficient 3 -- `34xx`: Set echo filter coefficient 4 -- `35xx`: Set echo filter coefficient 5 -- `36xx`: Set echo filter coefficient 6 -- `37xx`: Set echo filter coefficient 7 +- `10xx`: set waveform. +- `11xx`: toggle noise mode. +- `12xx`: toggle echo on this channel. +- `13xx`: toggle pitch modulation. +- `14xy`: toggle inverting the left or right channels (x: left, y: right). +- `15xx`: set envelope mode. + - 0: ADSR. + - 1: gain (direct). + - 2: linear decrement. + - 3: exponential decrement. + - 4: linear increment. + - 5: bent line (inverse log) increment. +- `16xx`: set gain (00 to 7F if direct, 00 to 1F otherwise). +- `18xx`: enable echo buffer. +- `19xx`: set echo delay + - goes from 0 to F. +- `1Axx`: set left echo channel volume. + - this is a signed number. + - 00 to 7F for 0 to 127. + - 80 to FF for -128 to -1. + - setting this to -128 is not recommended as it may cause echo output to overflow and therefore click. +- `1Bxx`: set right echo channel volume. + - this is a signed number. + - 00 to 7F for 0 to 127. + - 80 to FF for -128 to -1. + - setting this to -128 is not recommended as it may cause echo output to overflow and therefore click. +- `1Cxx`: set echo feedback. + - this is a signed number. + - 00 to 7F for 0 to 127. + - 80 to FF for -128 to -1. + - setting this to -128 is not recommended as it may cause echo output to overflow and therefore click. +- `1Dxx`: set noise generator frequency (00 to 1F). +- `20xx`: set attack (0 to F). + - only in ADSR envelope mode. +- `21xx`: set decay (0 to 7). + - only in ADSR envelope mode. +- `22xx`: set sustain (0 to 7). + - only in ADSR envelope mode. +- `23xx`: set release (00 to 1F). + - only in ADSR envelope mode. +- `30xx`: set echo filter coefficient 0. +- `31xx`: set echo filter coefficient 1. +- `32xx`: set echo filter coefficient 2. +- `33xx`: set echo filter coefficient 3. +- `34xx`: set echo filter coefficient 4. +- `35xx`: set echo filter coefficient 5. +- `36xx`: set echo filter coefficient 6. +- `37xx`: set echo filter coefficient 7. + - all of these are signed numbers. + - 00 to 7F for 0 to 127. + - 80 to FF for -128 to -1. + - make sure the sum of these is between -128 or 127. + - failure to comply may result in overflow and therefore clicking. diff --git a/papers/doc/7-systems/soundunit.md b/papers/doc/7-systems/soundunit.md index 34cc16b4e..4f1234619 100644 --- a/papers/doc/7-systems/soundunit.md +++ b/papers/doc/7-systems/soundunit.md @@ -1,5 +1,16 @@ # tildearrow Sound Unit -This is a fantasy sound chip, used in the specs2 fantasy computer designed by tildearrow. It includes native support for sample playback, but with only 8KB or 64KB of sample data, depending on the configuration used. Since 0.6pre1, this sound chip is no longer hidden by default and can be accessed through the module creation screen and can be added or removed. + +a fantasy sound chip, used in the specs2 fantasy computer designed by tildearrow. + +it has the following capabilities: +- 8 channels of either waveform or sample +- stereo sound +- 8 waveforms (pulse, saw, sine, triangle, noise, periodic noise, XOR sine and XOR triangle) +- 128 widths for the pulse wave +- per-channel resonant filter +- ring modulation +- volume, frequency and cutoff sweep units (per-channel) +- phase reset timer (per-channel) # effects diff --git a/papers/doc/7-systems/vic20.md b/papers/doc/7-systems/vic20.md index 0c8186318..cf9a8a46e 100644 --- a/papers/doc/7-systems/vic20.md +++ b/papers/doc/7-systems/vic20.md @@ -1,11 +1,18 @@ # Commodore VIC-20 -The Commodore VIC-20 was Commodore's major attempt at making a personal home computer, and is the percursor to the Commodore 64. The VIC-20 was also known as the VC-20 in Germany, and the VIC-1001 in Japan. +the Commodore VIC-20 was Commodore's major attempt at making a personal home computer, and is the percursor to the Commodore 64. -It has 4 PSG voices that has a limited but wide tuning range, and like the SN76489, the last voice is dedicated to playing pseudo-white noise. +it was also known as the VC-20 in Germany, and the VIC-1001 in Japan. -The 3 pulse wave channels also have different octaves that they can play notes on. The first channel is the bass channel, and it can play notes from octave 1. The next is the 'mid/chord' channel, and it plays notes from octave 2. And rather obviously, the 3rd pulse channel is typically the lead channel, can play notes from octave 3. +it has 4 voices that have a limited but wide tuning range, and like the SN76489 and T6W28, the last voice is dedicated to playing noise. + +the 3 pulse wave channels also have different octaves that they can play notes on: +- the first channel is the bass channel, and it can play notes from octave 1. +- the next is the 'mid/chord' channel, and it plays notes from octave 2. +- and rather obviously, the 3rd pulse channel is typically the lead channel, can play notes from octave 3. + +these channels are not referred as "square" wave channels since a technique to play 15 additional pulse-like waveforms has been discovered long after the VIC-20's release. ## effect commands - - `10xx` Switch waveform (`xx` from `00` to `0F`) \ No newline at end of file + - `10xx` Switch waveform (`xx` from `00` to `0F`) diff --git a/papers/doc/7-systems/vrc6.md b/papers/doc/7-systems/vrc6.md index c89678b47..0ec4c8b26 100644 --- a/papers/doc/7-systems/vrc6.md +++ b/papers/doc/7-systems/vrc6.md @@ -1,11 +1,11 @@ # Konami VRC6 -the most popular expansion chip to the NES' sound system. +the most popular expansion chip to the Famicom's sound system. the chip has 2 pulse wave channels and one sawtooth channel. volume register is 4 bit for pulse wave and 6 bit for sawtooth, but sawtooth output is corrupted when volume register value is too high. because this register is actually an 8 bit accumulator, its output may wrap around. -For that reason, the sawtooth channel has it's own instrument type. Setting volume macro and pattern editor volume setting too high (above 42/2A) will distort the waveform. +for that reason, the sawtooth channel has its own instrument type. setting volume macro and/or pattern editor volume setting too high (above 42/2A) may distort the waveform. pulse wave duty cycle is 8-level. it can be ignored and it has potential for DAC at this case: volume register in this mode is DAC output and it can be PCM playback through this mode. Furnace supports this routine for PCM playback, but it consumes a lot of CPU time in real hardware (even if conjunction with VRC6's integrated IRQ timer). diff --git a/papers/doc/7-systems/wonderswan.md b/papers/doc/7-systems/wonderswan.md index 44657decb..21a1a9261 100644 --- a/papers/doc/7-systems/wonderswan.md +++ b/papers/doc/7-systems/wonderswan.md @@ -1,8 +1,12 @@ # WonderSwan -A handheld console released only in Japan by Bandai. Designed by the same people behind Game Boy and Virtual Boy, it has lots of similar elements from those two systems in the sound department. +a handheld console released only in Japan by Bandai, designed by the same people behind Game Boy and Virtual Boy. +for this reason it has lots of similar elements from those two systems in the sound department. -It has 4 wavetable channels, channel #2 could play PCM, channel #3 has hardware sweep and channel #4 could play noise. +it has 4 wavetable channels. some of them have additional capabilities: +- the second channel could play samples +- the third one has hardware sweep +- the fourth one also does noise # effects diff --git a/papers/doc/7-systems/ym2151.md b/papers/doc/7-systems/ym2151.md index 854a370c9..60764d193 100644 --- a/papers/doc/7-systems/ym2151.md +++ b/papers/doc/7-systems/ym2151.md @@ -4,7 +4,7 @@ the sound chip powering several arcade boards and the Sharp X1/X68000. Eight 4-o it also was present on several pinball machines and synthesizers of the era, and later surpassed by the YM2414 (OPZ) present in the world-famous TX81Z. -in most arcade boards the chip was used in combination with a PCM chip, like [SegaPCM](segapcm.md) or OKI's line of [ADPCM](msm6258.md) [chips](msm6295.md). +in most arcade boards the chip was used in combination with a PCM chip, like [SegaPCM](segapcm.md) or [OKI's line of ADPCM chips](oki.md). # effects diff --git a/papers/doc/7-systems/ym2203.md b/papers/doc/7-systems/ym2203.md index 6b0bbf8d9..2c1f53b40 100644 --- a/papers/doc/7-systems/ym2203.md +++ b/papers/doc/7-systems/ym2203.md @@ -21,7 +21,7 @@ several variants of this chip were released as well, with more features. - `y` is the mutliplier. - `18xx`: toggle extended channel 3 mode. - 0 disables it and 1 enables it. - - only in extended channel 3 system. + - only in extended channel 3 chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/ym2608.md b/papers/doc/7-systems/ym2608.md index 736258a38..1581189ef 100644 --- a/papers/doc/7-systems/ym2608.md +++ b/papers/doc/7-systems/ym2608.md @@ -21,7 +21,7 @@ the YM2610 (OPNB) and YM2610B chips are very similar to this one, but the built- - `y` is the mutliplier. - `18xx`: toggle extended channel 3 mode. - 0 disables it and 1 enables it. - - only in extended channel 3 system. + - only in extended channel 3 chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/ym2610.md b/papers/doc/7-systems/ym2610.md index ec405efef..22df25d87 100644 --- a/papers/doc/7-systems/ym2610.md +++ b/papers/doc/7-systems/ym2610.md @@ -19,7 +19,7 @@ its soundchip is a 4-in-1: 4ch 4-op FM, YM2149 (AY-3-8910 clone) and 2 different - `y` is the mutliplier. - `18xx`: toggle extended channel 2 mode. - 0 disables it and 1 enables it. - - only in extended channel 2 system. + - only in extended channel 2 chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. @@ -96,4 +96,4 @@ its soundchip is a 4-in-1: 4ch 4-op FM, YM2149 (AY-3-8910 clone) and 2 different - `5Cxx`: set D2R/SR of operator 1. - `5Dxx`: set D2R/SR of operator 2. - `5Exx`: set D2R/SR of operator 3. -- `5Fxx`: set D2R/SR of operator 4. \ No newline at end of file +- `5Fxx`: set D2R/SR of operator 4. diff --git a/papers/doc/7-systems/ym2610b.md b/papers/doc/7-systems/ym2610b.md index 4133681ff..241366f44 100644 --- a/papers/doc/7-systems/ym2610b.md +++ b/papers/doc/7-systems/ym2610b.md @@ -18,7 +18,7 @@ it is backward compatible with the original chip. - `y` is the mutliplier. - `18xx`: toggle extended channel 3 mode. - 0 disables it and 1 enables it. - - only in extended channel 3 system. + - only in extended channel 3 chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/ym2612.md b/papers/doc/7-systems/ym2612.md index 6b2212017..56b1a3b18 100644 --- a/papers/doc/7-systems/ym2612.md +++ b/papers/doc/7-systems/ym2612.md @@ -21,7 +21,7 @@ For 0.6pre1, Furnace can now support advanced YM2612 features that [Fractal](ht - this only works on channel 6. - `18xx`: toggle extended channel 3 mode. - 0 disables it and 1 enables it. - - only in extended channel 3 system. + - only in extended channel 3 chip. - `19xx`: set attack of all operators. - `1Axx`: set attack of operator 1. - `1Bxx`: set attack of operator 2. diff --git a/papers/doc/7-systems/ymz280b.md b/papers/doc/7-systems/ymz280b.md index 097fa6a4a..b3a82b868 100644 --- a/papers/doc/7-systems/ymz280b.md +++ b/papers/doc/7-systems/ymz280b.md @@ -1,6 +1,8 @@ # Yamaha YMZ280B (PCMD8) -8ch PCM/ADPCM sample-based synthesizer designed for use with arcade machines. Lived throughout mid to late 90s. It has 16-level stereo panning, up to 16-bit PCM and up to 16Mbytes of external PCM data. +8-channel PCM/ADPCM sample-based sound chip designed for use with arcade machines. it lived throughout mid to late 90s. + +it has 16-level stereo panning, up to 16-bit PCM and up to 16MB of external PCM data. # effects diff --git a/papers/doc/7-systems/zxbeep.md b/papers/doc/7-systems/zxbeep.md index 9e25284bf..6504ce98e 100644 --- a/papers/doc/7-systems/zxbeep.md +++ b/papers/doc/7-systems/zxbeep.md @@ -1,8 +1,8 @@ -# ZX Spectrum Speaker +# ZX Spectrum beeper -Rather than having a dedicated sound synthesizer, early ZX Spectrum models had one piezo beeper, controlled by Z80 CPU and ULA chip. It's capabilities should be on par with an IBM PC speaker... right? +rather than having a dedicated sound synthesizer, early ZX Spectrum models had one piezo beeper, controlled by Z80 CPU and ULA chip. its capabilities should be on par with an IBM PC speaker... right? -Not really - very soon talented programmers found out ways to output much more than one square wave channel. A lot of ZX beeper routines do exist, but as of 0.6pre1 Furnace supports only one - Follin-like engine with 6 channels of narrow pulse wave and click drums. +not really - very soon talented programmers found out ways to output much more than one square wave channel. a lot of ZX beeper routines do exist, but as of 0.6 Furnace supports only a Follin/SFX-like engine with 6 channels of narrow pulse wave and click drums. # effects @@ -10,4 +10,4 @@ Not really - very soon talented programmers found out ways to output much more t - `17xx`: trigger overlay drum. - `xx` is the sample number. - overlay drums are 1-bit and always play at 55930Hz (NTSC) or 55420Hz (PAL). - - the maximum length is 2048! \ No newline at end of file + - the maximum length is 2048! From 8e64ecd23ad5ac7ef3ce7b22d79615c957469551 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 00:53:12 -0500 Subject: [PATCH 20/57] Virtual Boy: fix sweep not working --- src/engine/platform/vb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index a57d92cdf..e750bd7b5 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -335,7 +335,7 @@ int DivPlatformVB::dispatch(DivCommand c) { chWrite(4,0x07,modulation); if (modulation!=0) { chan[c.chan].envHigh&=~0x70; - chan[c.chan].envHigh|=0x10; + chan[c.chan].envHigh|=0x40; } else { chan[c.chan].envHigh&=~0x70; } From 3038f65fab8483653d1a992895ab69389ad17202 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:00:28 -0500 Subject: [PATCH 21/57] Virtual Boy: fix modulation --- src/engine/platform/vb.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index e750bd7b5..1094731ed 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -317,12 +317,12 @@ int DivPlatformVB::dispatch(DivCommand c) { break; case DIV_CMD_FDS_MOD_DEPTH: // set modulation if (c.chan!=4) break; - modulation=(c.value<<4)&15; + modulation=(c.value&15)<<4; modType=true; chWrite(4,0x07,modulation); if (modulation!=0) { chan[c.chan].envHigh&=~0x70; - chan[c.chan].envHigh|=0x40|((c.value&15)<<4); + chan[c.chan].envHigh|=0x40|(c.value&0xf0); } else { chan[c.chan].envHigh&=~0x70; } From 0d4db39c14d4ffffcd6e0624cb291678e1b1835f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:01:31 -0500 Subject: [PATCH 22/57] add Virtual Boy docs --- papers/doc/7-systems/virtual-boy.md | 43 +++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 papers/doc/7-systems/virtual-boy.md diff --git a/papers/doc/7-systems/virtual-boy.md b/papers/doc/7-systems/virtual-boy.md new file mode 100644 index 000000000..94a2d0492 --- /dev/null +++ b/papers/doc/7-systems/virtual-boy.md @@ -0,0 +1,43 @@ +# Virtual Boy + +a "portable" video game console made by Nintendo in the '90's. + +it supposedly was the beginning of virtual reality... nah, instead it failed to sell well because you use it for 15 minutes and then you get a headache. + +its sound generation chip is called Virtual Sound Unit (VSU), a wavetable chip that is a lot like PC Engine, but unlike that, the waves are twice as tall, it doesn't go too low in terms of frequency (~D-2), and the last channel (yep, it has 6 channels) is a noise one. + +additionally, channel 5 offers a modulation/sweep unit. the former is similar to FDS' but has much reduced speed control. + +# effects + +- `10xx`: set waveform. +- `11xx`: set noise length (0 to 7). + - only in the noise channel. +- `12xy`: setup envelope. + - `x` determines whether envelope is enabled or not. + - 0: disabled + - 1: enabled + - 3: enabled and loop + - yeah, the value 2 isn't useful. + - `y` sets the speed and direction. + - 0-7: down + - 8-F: up +- `13xy`: setup sweep. + - `x` sets the speed. + - 0 and 8 are "speed 0" - sweep is ineffective. + - `y` sets the shift (0 to 7). + - 8 and higher will mute the channel. + - only in channel 5. +- `14xy`: setup modulation. + - `x` determines whether it's enabled or not. + - 0: disabled + - 1: enabled + - 3: enabled and loop + - 2 isn't useful here either. + - `y` sets the speed. + - 0 and 8 are "speed 0" - modulation is ineffective. + - no, you can't really do Yamaha FM using this. + - only in channel 5. +- `15xx`: set modulation wave. + - `xx` points to a wavetable. it should have a height of 255. + - this is an alternative to setting the modulation wave through the instrument. From 2160b6e8857b5d904e8d90f4f55eb6ab64134a8e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:05:30 -0500 Subject: [PATCH 23/57] add T6W28 docs --- papers/doc/7-systems/t6w28.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 papers/doc/7-systems/t6w28.md diff --git a/papers/doc/7-systems/t6w28.md b/papers/doc/7-systems/t6w28.md new file mode 100644 index 000000000..9083cb7a2 --- /dev/null +++ b/papers/doc/7-systems/t6w28.md @@ -0,0 +1,11 @@ +# Toshiba T6W28 + +an enhanced SN76489 derivative. same 4 channels, but with stereo (soft panning!) and noise frequency being fully independent of channel 3's. + +this chip was used in Neo Geo Pocket. + +# effects + +- `20xx`: set noise mode. + - 0: thin pulse. + - 1: noise. From dfea2fc684605e5e358d6ac16820e6c298391486 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:10:41 -0500 Subject: [PATCH 24/57] doc: update chip list --- papers/doc/7-systems/README.md | 65 ++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/papers/doc/7-systems/README.md b/papers/doc/7-systems/README.md index 5ebe97362..1ec5aa305 100644 --- a/papers/doc/7-systems/README.md +++ b/papers/doc/7-systems/README.md @@ -2,38 +2,51 @@ this is a list of sound chips that Furnace supports, including effects. -- [Yamaha YM2612](ym2612.md) -- [TI SN76489](sms.md) -- [Yamaha OPLL](opll.md) -- [Game Boy](game-boy.md) -- [PC Engine/TurboGrafx-16](pce.md) -- [NES](nes.md) -- [Commodore 64](c64.md) -- [Yamaha YM2151](ym2151.md) -- [SegaPCM](segapcm.md) -- [Neo Geo/YM2610](ym2610.md) -- [Taito Arcade/YM2610B](ym2610b.md) -- [AY-3-8910](ay8910.md) - [Amiga](amiga.md) -- [Capcom QSound](qsound.md) -- [Atari 2600](tia.md) -- [Philips SAA1099](saa1099.md) +- [AY-3-8910](ay8910.md) - [Microchip AY8930](ay8930.md) -- [VERA](vera.md) -- [tildearrow Sound Unit](soundunit.md) -- [Seta/Allumer X1-010](x1-010.md) -- [WonderSwan](wonderswan.md) - [Bubble System WSG](bubblesystem.md) +- [Commodore 64](c64.md) +- [Commodore PET](pet.md) +- [Commodore VIC-20](vic20.md) +- [Generic PCM DAC](dac.md) +- [Famicom Disk System](fds.md) +- [Game Boy](game-boy.md) +- [Konami SCC](scc.md) +- [Konami VRC6](vrc6.md) +- [Atari Lynx](lynx.md) - [Namco 163](n163.md) - [Namco WSG](namco.md) -- [Yamaha OPL](opl.md) -- [PC Speaker](pcspkr.md) -- [Commodore PET](pet.md) -- [Konami SCC](scc.md) -- [Commodore VIC-20](vic20.md) -- [Konami VRC6](vrc6.md) -- [Famicom Disk System](fds.md) +- [NES](nes.md) - [Nintendo MMC5](mmc5.md) +- [OKI MSM5232](msm5232.md) +- [OKI MSM6258](msm6258.md) +- [OKI MSM6295](msm6295.md) +- [PC Engine/TurboGrafx-16](pce.md) +- [PC Speaker](pcspkr.md) +- [Philips SAA1099](saa1099.md) +- [Capcom QSound](qsound.md) +- [Ricoh RF5C68](ricoh.md) +- [SegaPCM](segapcm.md) +- [Seta/Allumer X1-010](x1-010.md) - [SNES](snes.md) +- [Atari 2600 (TIA)](tia.md) +- [tildearrow Sound Unit](soundunit.md) +- [TI SN76489](sms.md) +- [Toshiba T6W28](t6w28.md) +- [VERA](vera.md) +- [WonderSwan](wonderswan.md) +- [Virtual Boy](virtual-boy.md) +- [Yamaha OPLL](opll.md) +- [Yamaha OPL](opl.md) +- [Yamaha YM2151](ym2151.md) +- [Yamaha YM2203](ym2203.md) +- [Yamaha YM2413](opz.md) +- [Yamaha YM2608](ym2608.md) +- [Neo Geo/YM2610](ym2610.md) +- [Taito Arcade/YM2610B](ym2610b.md) +- [Yamaha YM2612](ym2612.md) +- [Yamaha YMZ280B](ymz280b.md) +- [ZX Spectrum Beeper](zxbeep.md) Furnace also reads .dmf files with the [Yamaha YMU759](ymu759.md) system, but... From 340a70653bf53f7d3b5fdeb551a097571993ce79 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:14:00 -0500 Subject: [PATCH 25/57] Virtual Boy: document reset register --- src/engine/platform/vb.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/platform/vb.cpp b/src/engine/platform/vb.cpp index 1094731ed..a8baab3cf 100644 --- a/src/engine/platform/vb.cpp +++ b/src/engine/platform/vb.cpp @@ -84,6 +84,8 @@ const char* regCheatSheetVB[]={ "S6EV0", "550", "S6EV1", "554", "S6RAM", "558", + + "RESET", "580", NULL }; From 285d81c716d5e157f1e4f82403797ba7b358552c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:27:39 -0500 Subject: [PATCH 26/57] T6W28: VGM export --- src/engine/sysDef.cpp | 2 +- src/engine/vgmOps.cpp | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 404f64057..63ff23eea 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1657,7 +1657,7 @@ void DivEngine::registerSystems() { sysDefs[DIV_SYSTEM_T6W28]=new DivSysDef( // 0x0a = wild guess. it may as well be 0x83 - "T6W28", NULL, 0xbf, 0x0a, 4, false, true, 0, false, 0, + "T6W28", NULL, 0xbf, 0x0a, 4, false, true, 0x160, false, 0, "an SN76489 derivative used in Neo Geo Pocket, has independent stereo volume and noise channel frequency.", {"Square 1", "Square 2", "Square 3", "Noise"}, {"S1", "S2", "S3", "NO"}, diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 815436fd6..c7d376a05 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -79,6 +79,14 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(0x90|(i<<5)|15); } break; + case DIV_SYSTEM_T6W28: + for (int i=0; i<4; i++) { + w->writeC(0x30); + w->writeC(0x90|(i<<5)|15); + w->writeC(0x50); + w->writeC(0x90|(i<<5)|15); + } + break; case DIV_SYSTEM_GB: // square 1 w->writeC(0xb3); @@ -497,6 +505,12 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(baseAddr2|12); w->writeC(1); break; + case DIV_SYSTEM_VBOY: + // isn't it amazing when a chip has a built-in reset command? + w->writeC(0xc7); + w->writeS_BE(baseAddr2S|(0x580>>2)); + w->writeC(0xff); + break; default: break; } @@ -559,6 +573,14 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(smsAddr); w->writeC(write.val); break; + case DIV_SYSTEM_T6W28: + if (write.addr) { + w->writeC(0x30); + } else { + w->writeC(0x50); + } + w->writeC(write.val); + break; case DIV_SYSTEM_GB: w->writeC(0xb3); w->writeC(baseAddr2|((write.addr-16)&0xff)); @@ -808,14 +830,14 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write } #define CHIP_VOL(_id,_mult) { \ - double _vol=fabs(song.systemVol[i])*4.0*_mult; \ + double _vol=fabs((float)song.systemVol[i])*4.0*_mult; \ if (_vol<0.0) _vol=0.0; \ if (_vol>32767.0) _vol=32767.0; \ chipVol.push_back((_id)|(0x80000000)|(((unsigned int)_vol)<<16)); \ } #define CHIP_VOL_SECOND(_id,_mult) { \ - double _vol=fabs(song.systemVol[i])*4.0*_mult; \ + double _vol=fabs((float)song.systemVol[i])*4.0*_mult; \ if (_vol<0.0) _vol=0.0; \ if (_vol>32767.0) _vol=32767.0; \ chipVol.push_back((_id)|(0x80000100)|(((unsigned int)_vol)<<16)); \ @@ -1362,6 +1384,13 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p howManyChips++; } break; + case DIV_SYSTEM_T6W28: + if (!hasSN) { + hasSN=0xc0000000|disCont[i].dispatch->chipClock; + CHIP_VOL(0,1.0); + willExport[i]=true; + } + break; default: break; } From ecd5662d9b3c766684cf25691623faf8d59abb81 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 01:29:02 -0500 Subject: [PATCH 27/57] T6W28: whoops fix VGM export --- src/engine/vgmOps.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index c7d376a05..883e1e464 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -1388,6 +1388,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (!hasSN) { hasSN=0xc0000000|disCont[i].dispatch->chipClock; CHIP_VOL(0,1.0); + snNoiseConfig=3; + snNoiseSize=15; willExport[i]=true; } break; From fdcabe448554fdd55c01b5a9f116ddee2c2a8470 Mon Sep 17 00:00:00 2001 From: smb123w64gb Date: Sun, 16 Oct 2022 10:14:51 -0700 Subject: [PATCH 28/57] Update Backward to work on ARM64 WIndows builds! --- extern/backward/backward.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extern/backward/backward.hpp b/extern/backward/backward.hpp index 04032a4dc..1e2251369 100644 --- a/extern/backward/backward.hpp +++ b/extern/backward/backward.hpp @@ -1159,6 +1159,10 @@ public: s.AddrPC.Offset = ctx_->Rip; s.AddrStack.Offset = ctx_->Rsp; s.AddrFrame.Offset = ctx_->Rbp; +#elif _M_ARM64 + s.AddrPC.Offset = ctx_->Pc; + s.AddrStack.Offset = ctx_->Sp; + s.AddrFrame.Offset = ctx_->Fp; #else s.AddrPC.Offset = ctx_->Eip; s.AddrStack.Offset = ctx_->Esp; @@ -1168,6 +1172,8 @@ public: if (!machine_type_) { #ifdef _M_X64 machine_type_ = IMAGE_FILE_MACHINE_AMD64; +#elif _M_ARM64 + machine_type_ = IMAGE_FILE_MACHINE_ARM64; #else machine_type_ = IMAGE_FILE_MACHINE_I386; #endif From b9b76bef0b4b40b65a77720032ec1b27396dd8be Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 17:57:24 -0500 Subject: [PATCH 29/57] GUI: fix unsigned detune --- src/gui/insEdit.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index ceda17a2e..8cfbf9ec5 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2571,7 +2571,7 @@ void FurnaceGUI::drawInsEdit() { int detune=(op.dt&7)-(settings.unsignedDetune?0:3); ImGui::TableNextColumn(); CENTER_VSLIDER; - if (CWVSliderInt("##DT",ImVec2(20.0f*dpiScale,sliderHeight),&detune,-3,4)) { PARAMETER + if (CWVSliderInt("##DT",ImVec2(20.0f*dpiScale,sliderHeight),&detune,settings.unsignedDetune?0:-3,settings.unsignedDetune?7:4)) { PARAMETER op.dt=detune+(settings.unsignedDetune?0:3); } @@ -2904,7 +2904,7 @@ void FurnaceGUI::drawInsEdit() { int detune=(op.dt&7)-(settings.unsignedDetune?0:3); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); - if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER + if (CWSliderInt("##DT",&detune,settings.unsignedDetune?0:-3,settings.unsignedDetune?7:4,tempID)) { PARAMETER op.dt=detune+(settings.unsignedDetune?0:3); } rightClickable @@ -2926,7 +2926,7 @@ void FurnaceGUI::drawInsEdit() { int detune=(op.dt&7)-(settings.unsignedDetune?0:3); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); - if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER + if (CWSliderInt("##DT",&detune,settings.unsignedDetune?0:-3,settings.unsignedDetune?7:4,tempID)) { PARAMETER op.dt=detune+(settings.unsignedDetune?0:3); } rightClickable @@ -3067,7 +3067,7 @@ void FurnaceGUI::drawInsEdit() { int detune=(op.dt&7)-(settings.unsignedDetune?0:3); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_DT)); - if (CWSliderInt("##DT",&detune,-3,4,tempID)) { PARAMETER + if (CWSliderInt("##DT",&detune,settings.unsignedDetune?0:-3,settings.unsignedDetune?7:4,tempID)) { PARAMETER op.dt=detune+(settings.unsignedDetune?0:3); } rightClickable } @@ -3442,7 +3442,7 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); - if (CWSliderInt("##DT",&detune,-3,4)) { PARAMETER + if (CWSliderInt("##DT",&detune,settings.unsignedDetune?0:-3,settings.unsignedDetune?7:4)) { PARAMETER op.dt=detune+(settings.unsignedDetune?0:3); } rightClickable ImGui::TableNextColumn(); From 2272028b106d87ca2523240484894ef9bfcf11eb Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 18:23:13 -0500 Subject: [PATCH 30/57] GUI: mixer changes mark song as modified --- src/gui/mixer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/mixer.cpp b/src/gui/mixer.cpp index 7d6f1671f..4897c64ac 100644 --- a/src/gui/mixer.cpp +++ b/src/gui/mixer.cpp @@ -33,6 +33,7 @@ void FurnaceGUI::drawMixer() { if (ImGui::SliderFloat("Master Volume",&e->song.masterVol,0,3,"%.2fx")) { if (e->song.masterVol<0) e->song.masterVol=0; if (e->song.masterVol>3) e->song.masterVol=3; + MARK_MODIFIED; } rightClickable for (int i=0; isong.systemLen; i++) { snprintf(id,31,"MixS%d",i); @@ -43,13 +44,17 @@ void FurnaceGUI::drawMixer() { ImGui::SameLine(ImGui::GetWindowWidth()-(82.0f*dpiScale)); if (ImGui::Checkbox("Invert",&doInvert)) { e->song.systemVol[i]^=128; + MARK_MODIFIED; } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); if (CWSliderScalar("Volume",ImGuiDataType_S8,&vol,&_ZERO,&_ONE_HUNDRED_TWENTY_SEVEN)) { e->song.systemVol[i]=(e->song.systemVol[i]&128)|vol; + MARK_MODIFIED; } rightClickable ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-(50.0f*dpiScale)); - CWSliderScalar("Panning",ImGuiDataType_S8,&e->song.systemPan[i],&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN); rightClickable + if (CWSliderScalar("Panning",ImGuiDataType_S8,&e->song.systemPan[i],&_MINUS_ONE_HUNDRED_TWENTY_SEVEN,&_ONE_HUNDRED_TWENTY_SEVEN)) { + MARK_MODIFIED; + } rightClickable ImGui::PopID(); } From 40108976c3c8fd6343b771abf91146c504055b71 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 18:28:42 -0500 Subject: [PATCH 31/57] GUI: more mark modified cases --- src/gui/gui.cpp | 6 ++++++ src/gui/songInfo.cpp | 1 + src/gui/sysManager.cpp | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 1fed0a51a..fc2de66c5 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3446,6 +3446,8 @@ bool FurnaceGUI::loop() { if (picked!=DIV_SYSTEM_NULL) { if (!e->addSystem(picked)) { showError("cannot add chip! ("+e->getLastError()+")"); + } else { + MARK_MODIFIED; } ImGui::CloseCurrentPopup(); if (e->song.autoSystem) { @@ -3471,6 +3473,7 @@ bool FurnaceGUI::loop() { DivSystem picked=systemPicker(); if (picked!=DIV_SYSTEM_NULL) { e->changeSystem(i,picked,preserveChanPos); + MARK_MODIFIED; if (e->song.autoSystem) { autoDetectSystem(); } @@ -3488,6 +3491,8 @@ bool FurnaceGUI::loop() { if (ImGui::MenuItem(fmt::sprintf("%d. %s##_SYSR%d",i+1,getSystemName(e->song.system[i]),i).c_str())) { if (!e->removeSystem(i,preserveChanPos)) { showError("cannot remove chip! ("+e->getLastError()+")"); + } else { + MARK_MODIFIED; } if (e->song.autoSystem) { autoDetectSystem(); @@ -4640,6 +4645,7 @@ bool FurnaceGUI::loop() { if (e->song.autoSystem) { autoDetectSystem(); updateWindowTitle(); + MARK_MODIFIED; } ImGui::CloseCurrentPopup(); } diff --git a/src/gui/songInfo.cpp b/src/gui/songInfo.cpp index 8d4e0999e..24ed67c0b 100644 --- a/src/gui/songInfo.cpp +++ b/src/gui/songInfo.cpp @@ -91,6 +91,7 @@ void FurnaceGUI::drawSongInfo() { autoDetectSystem(); updateWindowTitle(); } + MARK_MODIFIED; } popToggleColors(); autoButtonSize=ImGui::GetItemRectSize().x; diff --git a/src/gui/sysManager.cpp b/src/gui/sysManager.cpp index 386d26583..cd82b84ca 100644 --- a/src/gui/sysManager.cpp +++ b/src/gui/sysManager.cpp @@ -62,6 +62,7 @@ void FurnaceGUI::drawSysManager() { if (dragItem->IsDataType("FUR_SYS")) { if (sysToMove!=i && sysToMove>=0) { e->swapSystem(sysToMove,i,preserveChanPos); + MARK_MODIFIED; } sysToMove=-1; } @@ -82,6 +83,7 @@ void FurnaceGUI::drawSysManager() { DivSystem picked=systemPicker(); if (picked!=DIV_SYSTEM_NULL) { e->changeSystem(i,picked,preserveChanPos); + MARK_MODIFIED; if (e->song.autoSystem) { autoDetectSystem(); } @@ -112,6 +114,8 @@ void FurnaceGUI::drawSysManager() { if (picked!=DIV_SYSTEM_NULL) { if (!e->addSystem(picked)) { showError("cannot add chip! ("+e->getLastError()+")"); + } else { + MARK_MODIFIED; } if (e->song.autoSystem) { autoDetectSystem(); From 6216e286f8df79f85d136a5a28dedc9cb22e3965 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 18:30:48 -0500 Subject: [PATCH 32/57] GUI: mark modified cases in wave editor --- src/gui/waveEdit.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 4ceb7714b..5509ca5b2 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -162,6 +162,7 @@ void FurnaceGUI::doGenerateWave() { } e->notifyWaveChange(curWave); + MARK_MODIFIED; } #define CENTER_TEXT(text) \ @@ -850,6 +851,7 @@ void FurnaceGUI::drawWaveEdit() { if (ImGui::InputText("##MMLWave",&mmlStringW)) { int actualData[256]; decodeMMLStrW(mmlStringW,actualData,wave->len,(waveSigned && !waveHex)?(-((wave->max+1)/2)):0,(waveSigned && !waveHex)?(wave->max/2):wave->max,waveHex); + MARK_MODIFIED; if (waveSigned && !waveHex) { for (int i=0; ilen; i++) { actualData[i]+=(wave->max+1)/2; From 81a2bce4d40cc20050e37a34268f512b2bcce37d Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 19:40:14 -0500 Subject: [PATCH 33/57] GUI: prepare for multiple asset load --- extern/igfd/ImGuiFileDialog.cpp | 8 +++++++- src/gui/gui.cpp | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/extern/igfd/ImGuiFileDialog.cpp b/extern/igfd/ImGuiFileDialog.cpp index 63ae3b879..328bccb31 100644 --- a/extern/igfd/ImGuiFileDialog.cpp +++ b/extern/igfd/ImGuiFileDialog.cpp @@ -3993,7 +3993,13 @@ namespace IGFD } else { fdi.SelectFileName(prFileDialogInternal, vInfos); if (prFileDialogInternal.puDLGselFun!=NULL) { - prFileDialogInternal.puDLGselFun(GetFilePathName().c_str()); + std::string argPath; + for (auto& i: GetSelection()) { + argPath=i.second; + } + if (!argPath.empty()) { + prFileDialogInternal.puDLGselFun(argPath.c_str()); + } } } } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index fc2de66c5..3a1931b65 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1759,7 +1759,14 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { "all files", ".*"}, "compatible files{.fur,.dmf,.mod},another option{.wav,.ttf},.*", workingDirTest, - dpiScale + dpiScale, + [](const char* path) { + if (path!=NULL) { + logI("Callback Result: %s",path); + } else { + logI("Callback Result: NULL"); + } + } ); break; case GUI_FILE_TEST_OPEN_MULTI: @@ -1772,7 +1779,13 @@ void FurnaceGUI::openFileDialog(FurnaceGUIFileDialogs type) { "compatible files{.fur,.dmf,.mod},another option{.wav,.ttf},.*", workingDirTest, dpiScale, - NULL, + [](const char* path) { + if (path!=NULL) { + logI("Callback Result: %s",path); + } else { + logI("Callback Result: NULL"); + } + }, true ); break; From 0f3ce6f61699e6ee69cb0db57e42768c8a14abcf Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 21:35:20 -0500 Subject: [PATCH 34/57] update to-do list --- TODO.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/TODO.md b/TODO.md index ca2ca1434..e8d551ab1 100644 --- a/TODO.md +++ b/TODO.md @@ -2,8 +2,6 @@ - POKEY - Pokémon Mini -- Virtual Boy -- T6W28 - (maybe) YM2612 CSM (no DualPCM) - port presets to new format - bug fixes From c3e2e902af887020815c6f8f3e336c7a18172be3 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 16 Oct 2022 21:35:25 -0500 Subject: [PATCH 35/57] prepare for possible DualPCM and MSM6258 VGM xprt --- src/engine/dispatch.h | 13 +++++++++++++ src/engine/platform/abstract.cpp | 3 +++ 2 files changed, 16 insertions(+) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 9484054b1..6963dfb87 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -261,6 +261,11 @@ struct DivRegWrite { addr(a), val(v) {} }; +struct DivDelayedWrite { + int time; + DivRegWrite write; +}; + struct DivDispatchOscBuffer { bool follow; unsigned int rate; @@ -313,6 +318,14 @@ class DivDispatch { */ virtual void acquire(short* bufL, short* bufR, size_t start, size_t len); + /** + * fill a write stream with data (e.g. for software-mixed PCM). + * @param stream the write stream. + * @param rate stream rate (e.g. 44100 for VGM). + * @param len number of samples. + */ + virtual void fillStream(std::vector& stream, int rate, size_t len); + /** * send a command to this dispatch. * @param c a DivCommand. diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 746e8e80f..cdff34f3a 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -22,6 +22,9 @@ void DivDispatch::acquire(short* bufL, short* bufR, size_t start, size_t len) { } +void DivDispatch::fillStream(std::vector& stream, int rate, size_t len) { +} + void DivDispatch::tick(bool sysTick) { } From 684b5a928bfef3cc512179edc674028e28099025 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 04:17:00 -0500 Subject: [PATCH 36/57] VGM export: prepare for "direct stream mode" this will eventually allow for DualPCM and MSM6258 export DO NOT USE YET --- src/engine/dispatch.h | 2 +- src/engine/engine.h | 4 +- src/engine/platform/abstract.cpp | 2 +- src/engine/sysDef.cpp | 6 +- src/engine/vgmOps.cpp | 247 ++++++++++++++++--------------- src/gui/gui.cpp | 11 +- src/gui/gui.h | 1 + 7 files changed, 147 insertions(+), 126 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 6963dfb87..ffd9e247c 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -324,7 +324,7 @@ class DivDispatch { * @param rate stream rate (e.g. 44100 for VGM). * @param len number of samples. */ - virtual void fillStream(std::vector& stream, int rate, size_t len); + virtual void fillStream(std::vector& stream, int sRate, size_t len); /** * send a command to this dispatch. diff --git a/src/engine/engine.h b/src/engine/engine.h index e524f0a42..f4ed7cf5e 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -431,7 +431,7 @@ class DivEngine { void processRow(int i, bool afterDelay); void nextOrder(); void nextRow(); - void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond); + void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, bool directStream); // returns true if end of song. bool nextTick(bool noAccum=false, bool inhibitLowLat=false); bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal); @@ -515,7 +515,7 @@ class DivEngine { // specify system to build ROM for. SafeWriter* buildROM(int sys); // dump to VGM. - SafeWriter* saveVGM(bool* sysToExport=NULL, bool loop=true, int version=0x171, bool patternHints=false); + SafeWriter* saveVGM(bool* sysToExport=NULL, bool loop=true, int version=0x171, bool patternHints=false, bool directStream=false); // dump to ZSM. SafeWriter* saveZSM(unsigned int zsmrate=60, bool loop=true); // dump command stream. diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index cdff34f3a..8b3239f05 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -22,7 +22,7 @@ void DivDispatch::acquire(short* bufL, short* bufR, size_t start, size_t len) { } -void DivDispatch::fillStream(std::vector& stream, int rate, size_t len) { +void DivDispatch::fillStream(std::vector& stream, int sRate, size_t len) { } void DivDispatch::tick(bool sysTick) { diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 63ff23eea..67f58a67f 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1553,7 +1553,7 @@ void DivEngine::registerSystems() { ); sysDefs[DIV_SYSTEM_MSM6258]=new DivSysDef( - "OKI MSM6258", NULL, 0xab, 0, 1, false, true, 0, false, 1U<=0xffff0000) { // Furnace special command + if (write.addr>=0xffff0000 && !directStream) { // Furnace special command unsigned char streamID=streamOff+((write.addr&0xff00)>>8); logD("writing stream command %x:%x with stream ID %d",write.addr,write.val,streamID); switch (write.addr&0xff) { @@ -843,7 +843,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write chipVol.push_back((_id)|(0x80000100)|(((unsigned int)_vol)<<16)); \ } -SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool patternHints) { +SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool patternHints, bool directStream) { if (version<0x150) { lastError="VGM version is too low"; return NULL; @@ -947,6 +947,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p int loopSample[DIV_MAX_CHANS]; bool sampleDir[DIV_MAX_CHANS]; std::vector chipVol; + std::vector delayedWrites[32]; for (int i=0; ilength8; } - if (writeDACSamples) for (int i=0; iwriteC(0x67); w->writeC(0x66); @@ -1596,7 +1597,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } } - if (writeNESSamples) for (int i=0; iwriteC(0x67); w->writeC(0x66); @@ -1607,7 +1608,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } } - if (writePCESamples) for (int i=0; iwriteC(0x67); w->writeC(0x66); @@ -1785,87 +1786,89 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p // initialize streams int streamID=0; - for (int i=0; iwriteC(0x90); - w->writeC(streamID); - w->writeC(0x02); - w->writeC(0); // port - w->writeC(0x2a); // DAC - - w->writeC(0x91); - w->writeC(streamID); - w->writeC(0); - w->writeC(1); - w->writeC(0); - - w->writeC(0x92); - w->writeC(streamID); - w->writeI(32000); // default - streamID++; - break; - case DIV_SYSTEM_NES: - w->writeC(0x90); - w->writeC(streamID); - w->writeC(20); - w->writeC(0); // port - w->writeC(0x11); // DAC - - w->writeC(0x91); - w->writeC(streamID); - w->writeC(7); - w->writeC(1); - w->writeC(0); - - w->writeC(0x92); - w->writeC(streamID); - w->writeI(32000); // default - streamID++; - break; - case DIV_SYSTEM_PCE: - for (int j=0; j<6; j++) { + if (!directStream) { + for (int i=0; iwriteC(0x90); w->writeC(streamID); - w->writeC(27); - w->writeC(j); // port - w->writeC(0x06); // select+DAC + w->writeC(0x02); + w->writeC(0); // port + w->writeC(0x2a); // DAC w->writeC(0x91); w->writeC(streamID); - w->writeC(5); + w->writeC(0); w->writeC(1); w->writeC(0); w->writeC(0x92); w->writeC(streamID); - w->writeI(16000); // default + w->writeI(32000); // default streamID++; - } - break; - case DIV_SYSTEM_SWAN: - w->writeC(0x90); - w->writeC(streamID); - w->writeC(isSecond[i]?0xa1:0x21); - w->writeC(0); // port - w->writeC(0x09); // DAC + break; + case DIV_SYSTEM_NES: + w->writeC(0x90); + w->writeC(streamID); + w->writeC(20); + w->writeC(0); // port + w->writeC(0x11); // DAC - w->writeC(0x91); - w->writeC(streamID); - w->writeC(0); - w->writeC(1); - w->writeC(0); + w->writeC(0x91); + w->writeC(streamID); + w->writeC(7); + w->writeC(1); + w->writeC(0); - w->writeC(0x92); - w->writeC(streamID); - w->writeI(24000); // default - streamID++; - break; - default: - break; + w->writeC(0x92); + w->writeC(streamID); + w->writeI(32000); // default + streamID++; + break; + case DIV_SYSTEM_PCE: + for (int j=0; j<6; j++) { + w->writeC(0x90); + w->writeC(streamID); + w->writeC(27); + w->writeC(j); // port + w->writeC(0x06); // select+DAC + + w->writeC(0x91); + w->writeC(streamID); + w->writeC(5); + w->writeC(1); + w->writeC(0); + + w->writeC(0x92); + w->writeC(streamID); + w->writeI(16000); // default + streamID++; + } + break; + case DIV_SYSTEM_SWAN: + w->writeC(0x90); + w->writeC(streamID); + w->writeC(isSecond[i]?0xa1:0x21); + w->writeC(0); // port + w->writeC(0x09); // DAC + + w->writeC(0x91); + w->writeC(streamID); + w->writeC(0); + w->writeC(1); + w->writeC(0); + + w->writeC(0x92); + w->writeC(streamID); + w->writeI(24000); // default + streamID++; + break; + default: + break; + } } } @@ -1894,10 +1897,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p break; } // stop all streams - for (int i=0; iwriteC(0x94); - w->writeC(i); - loopSample[i]=-1; + if (!directStream) { + for (int i=0; iwriteC(0x94); + w->writeC(i); + loopSample[i]=-1; + } } if (!playing) { @@ -1929,63 +1934,69 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p for (int i=0; i& writes=disCont[i].dispatch->getRegisterWrites(); for (DivRegWrite& j: writes) { - performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i]); + performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],directStream); writeCount++; } writes.clear(); } // check whether we need to loop int totalWait=cycles>>MASTER_CLOCK_PREC; - for (int i=0; i=0) { - loopTimer[i]-=(loopFreq[i]/44100.0)*(double)totalWait; + if (directStream) { + for (int i=0; ifillStream(delayedWrites[i],44100,totalWait); } - } - bool haveNegatives=false; - for (int i=0; i=0) { - if (loopTimer[i]<0) { - haveNegatives=true; + } else { + for (int i=0; i=0) { + loopTimer[i]-=(loopFreq[i]/44100.0)*(double)totalWait; } } - } - while (haveNegatives) { - // finish all negatives - int nextToTouch=-1; + bool haveNegatives=false; for (int i=0; i=0) { if (loopTimer[i]<0) { - if (nextToTouch>=0) { - if (loopTimer[nextToTouch]>loopTimer[i]) nextToTouch=i; - } else { - nextToTouch=i; - } + haveNegatives=true; } } } - if (nextToTouch>=0) { - double waitTime=totalWait+(loopTimer[nextToTouch]*(44100.0/MAX(1,loopFreq[nextToTouch]))); - if (waitTime>0) { - w->writeC(0x61); - w->writeS(waitTime); - logV("wait is: %f",waitTime); - totalWait-=waitTime; - tickCount+=waitTime; - } - if (loopSample[nextToTouch]getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)) { - w->writeC(0x93); - w->writeC(nextToTouch); - w->writeI(sampleOff8[loopSample[nextToTouch]]+sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); - w->writeC(0x81); - w->writeI(sample->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)-sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); + while (haveNegatives) { + // finish all negatives + int nextToTouch=-1; + for (int i=0; i=0) { + if (loopTimer[i]<0) { + if (nextToTouch>=0) { + if (loopTimer[nextToTouch]>loopTimer[i]) nextToTouch=i; + } else { + nextToTouch=i; + } + } } } - loopSample[nextToTouch]=-1; - } else { - haveNegatives=false; + if (nextToTouch>=0) { + double waitTime=totalWait+(loopTimer[nextToTouch]*(44100.0/MAX(1,loopFreq[nextToTouch]))); + if (waitTime>0) { + w->writeC(0x61); + w->writeS(waitTime); + logV("wait is: %f",waitTime); + totalWait-=waitTime; + tickCount+=waitTime; + } + if (loopSample[nextToTouch]getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)) { + w->writeC(0x93); + w->writeC(nextToTouch); + w->writeI(sampleOff8[loopSample[nextToTouch]]+sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); + w->writeC(0x81); + w->writeI(sample->getLoopEndPosition(DIV_SAMPLE_DEPTH_8BIT)-sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)); + } + } + loopSample[nextToTouch]=-1; + } else { + haveNegatives=false; + } } } // write wait diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 3a1931b65..a66567ede 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -3390,6 +3390,14 @@ bool FurnaceGUI::loop() { "pattern indexes are ordered as they appear in the song." ); } + ImGui::Checkbox("direct stream mode",&vgmExportDirectStream); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip( + "required for DualPCM and MSM6258 export.\n\n" + "allows for volume/direction changes when playing samples,\n" + "at the cost of a massive increase in file size." + ); + } ImGui::Text("chips to export:"); bool hasOneAtLeast=false; for (int i=0; isong.systemLen; i++) { @@ -4161,7 +4169,7 @@ bool FurnaceGUI::loop() { break; } case GUI_FILE_EXPORT_VGM: { - SafeWriter* w=e->saveVGM(willExport,vgmExportLoop,vgmExportVersion,vgmExportPatternHints); + SafeWriter* w=e->saveVGM(willExport,vgmExportLoop,vgmExportVersion,vgmExportPatternHints,vgmExportDirectStream); if (w!=NULL) { FILE* f=ps_fopen(copyOfName.c_str(),"wb"); if (f!=NULL) { @@ -5309,6 +5317,7 @@ FurnaceGUI::FurnaceGUI(): vgmExportLoop(true), zsmExportLoop(true), vgmExportPatternHints(false), + vgmExportDirectStream(false), portrait(false), mobileMenuOpen(false), wantCaptureKeyboard(false), diff --git a/src/gui/gui.h b/src/gui/gui.h index dd1fa92f1..fc47d6d8d 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1035,6 +1035,7 @@ class FurnaceGUI { std::deque recentFile; bool quit, warnQuit, willCommit, edit, modified, displayError, displayExporting, vgmExportLoop, zsmExportLoop, vgmExportPatternHints; + bool vgmExportDirectStream; bool portrait, mobileMenuOpen; bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu; bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly; From 4723ed3972a54a4af81908196b3f883a38f31779 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 14:25:30 -0500 Subject: [PATCH 37/57] VGM: experimental direct stream mode for YM2612 --- src/engine/dispatch.h | 3 +++ src/engine/platform/genesis.cpp | 32 +++++++++++++++++++++--------- src/engine/platform/genesis.h | 3 ++- src/engine/vgmOps.cpp | 35 +++++++++++++++++++++++++++++++++ src/main.cpp | 9 ++++++++- 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index ffd9e247c..4c9fb2f29 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -264,6 +264,9 @@ struct DivRegWrite { struct DivDelayedWrite { int time; DivRegWrite write; + DivDelayedWrite(int t, unsigned int a, unsigned short v): + time(t), + write(a,v) {} }; struct DivDispatchOscBuffer { diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 480ecb441..0eb4aebb3 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -27,11 +27,11 @@ #define IS_REALLY_MUTED(x) (isMuted[x] && (x<5 || !softPCM || (isMuted[5] && isMuted[6]))) -void DivPlatformGenesis::processDAC() { +void DivPlatformGenesis::processDAC(int iRate) { if (softPCM) { softPCMTimer+=chipClock/576; - if (softPCMTimer>rate) { - softPCMTimer-=rate; + if (softPCMTimer>iRate) { + softPCMTimer-=iRate; int sample=0; for (int i=5; i<7; i++) { @@ -75,14 +75,14 @@ void DivPlatformGenesis::processDAC() { } else { if (!chan[5].dacReady) { chan[5].dacDelay+=32000; - if (chan[5].dacDelay>=rate) { - chan[5].dacDelay-=rate; + if (chan[5].dacDelay>=iRate) { + chan[5].dacDelay-=iRate; chan[5].dacReady=true; } } if (chan[5].dacMode && chan[5].dacSample!=-1) { chan[5].dacPeriod+=chan[5].dacRate; - if (chan[5].dacPeriod>=rate) { + if (chan[5].dacPeriod>=iRate) { DivSample* s=parent->getSample(chan[5].dacSample); if (s->samples>0) { if (!isMuted[5]) { @@ -106,7 +106,7 @@ void DivPlatformGenesis::processDAC() { rWrite(0x2b,0); } } - while (chan[5].dacPeriod>=rate) chan[5].dacPeriod-=rate; + while (chan[5].dacPeriod>=iRate) chan[5].dacPeriod-=iRate; } else { chan[5].dacSample=-1; } @@ -120,7 +120,7 @@ void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, s static int os[2]; for (size_t h=start; hdebug_engine(); for (size_t h=start; h& stream, int sRate, size_t len) { + while (!writes.empty()) writes.pop_front(); + for (size_t i=0; i& stream, int sRate, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); DivMacroInt* getChanMacroInt(int ch); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 582eafbd0..01d01ac88 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -948,6 +948,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p bool sampleDir[DIV_MAX_CHANS]; std::vector chipVol; std::vector delayedWrites[32]; + std::vector> sortedWrites; for (int i=0; i>MASTER_CLOCK_PREC; if (directStream) { + // render stream of all chips for (int i=0; ifillStream(delayedWrites[i],44100,totalWait); + for (DivDelayedWrite& j: delayedWrites[i]) { + sortedWrites.push_back(std::pair(i,j)); + } + delayedWrites[i].clear(); + } + + if (!sortedWrites.empty()) { + // sort if more than one chip + if (song.systemLen>1) { + std::sort(sortedWrites.begin(),sortedWrites.end(),[](const std::pair& a, const std::pair& b) -> bool { + return a.second.time& i: sortedWrites) { + if (i.second.time>lastOne) { + // write delay + int delay=i.second.time-lastOne; + if (delay>16) { + w->writeC(0x61); + w->writeS(totalWait); + } else if (delay>0) { + w->writeC(0x70+delay-1); + } + lastOne=i.second.time; + } + // write write + performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],directStream); + } + sortedWrites.clear(); + totalWait-=lastOne; } } else { for (int i=0; i params; @@ -122,6 +123,11 @@ TAParamResult pBinary(String val) { return TA_PARAM_SUCCESS; } +TAParamResult pDirect(String val) { + vgmOutDirect=true; + return TA_PARAM_SUCCESS; +} + TAParamResult pLogLevel(String val) { if (val=="trace") { logLevel=LOGLEVEL_TRACE; @@ -289,6 +295,7 @@ void initParams() { params.push_back(TAParam("a","audio",true,pAudio,"jack|sdl","set audio engine (SDL by default)")); params.push_back(TAParam("o","output",true,pOutput,"","output audio to file")); params.push_back(TAParam("O","vgmout",true,pVGMOut,"","output .vgm data")); + params.push_back(TAParam("D","direct",false,pDirect,"","set VGM export direct stream mode")); params.push_back(TAParam("Z","zsmout",true,pZSMOut,"","output .zsm data for Commander X16 Zsound")); params.push_back(TAParam("C","cmdout",true,pCmdOut,"","output command stream")); params.push_back(TAParam("b","binary",false,pBinary,"","set command stream output format to binary")); @@ -490,7 +497,7 @@ int main(int argc, char** argv) { } } if (vgmOutName!="") { - SafeWriter* w=e.saveVGM(); + SafeWriter* w=e.saveVGM(NULL,true,0x171,false,vgmOutDirect); if (w!=NULL) { FILE* f=fopen(vgmOutName.c_str(),"wb"); if (f!=NULL) { From 4dda45116e625b5badd1e7ef32e39e5f5973ffaa Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 14:28:41 -0500 Subject: [PATCH 38/57] VGM export: fix stream command glitch in direct --- src/engine/vgmOps.cpp | 62 ++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 01d01ac88..4275984db 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -515,37 +515,39 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write break; } } - if (write.addr>=0xffff0000 && !directStream) { // Furnace special command - unsigned char streamID=streamOff+((write.addr&0xff00)>>8); - logD("writing stream command %x:%x with stream ID %d",write.addr,write.val,streamID); - switch (write.addr&0xff) { - case 0: // play sample - if (write.valwriteC(0x95); - w->writeC(streamID); - w->writeS(write.val); // sample number - w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0)|(sampleDir[streamID]?0x10:0)); // flags - if (sample->isLoopable() && !sampleDir[streamID]) { - loopTimer[streamID]=sample->length8; - loopSample[streamID]=write.val; + if (write.addr>=0xffff0000) { // Furnace special command + if (!directStream) { + unsigned char streamID=streamOff+((write.addr&0xff00)>>8); + logD("writing stream command %x:%x with stream ID %d",write.addr,write.val,streamID); + switch (write.addr&0xff) { + case 0: // play sample + if (write.valwriteC(0x95); + w->writeC(streamID); + w->writeS(write.val); // sample number + w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0)|(sampleDir[streamID]?0x10:0)); // flags + if (sample->isLoopable() && !sampleDir[streamID]) { + loopTimer[streamID]=sample->length8; + loopSample[streamID]=write.val; + } } - } - break; - case 1: // set sample freq - w->writeC(0x92); - w->writeC(streamID); - w->writeI(write.val); - loopFreq[streamID]=write.val; - break; - case 2: // stop sample - w->writeC(0x94); - w->writeC(streamID); - loopSample[streamID]=-1; - break; - case 3: // set sample direction - sampleDir[streamID]=write.val; - break; + break; + case 1: // set sample freq + w->writeC(0x92); + w->writeC(streamID); + w->writeI(write.val); + loopFreq[streamID]=write.val; + break; + case 2: // stop sample + w->writeC(0x94); + w->writeC(streamID); + loopSample[streamID]=-1; + break; + case 3: // set sample direction + sampleDir[streamID]=write.val; + break; + } } return; } From ed12ca5bd8191e169814b9c030300b4c8720e28e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 14:31:37 -0500 Subject: [PATCH 39/57] VGM export: get Fractal template export working --- src/engine/vgmOps.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 4275984db..3b2b87b39 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -34,6 +34,8 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write switch (sys) { case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612_EXT: + case DIV_SYSTEM_YM2612_FRAC: + case DIV_SYSTEM_YM2612_FRAC_EXT: for (int i=0; i<3; i++) { // set SL and RR to highest w->writeC(2|baseAddr1); w->writeC(0x80+i); @@ -554,6 +556,8 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write switch (sys) { case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612_EXT: + case DIV_SYSTEM_YM2612_FRAC: + case DIV_SYSTEM_YM2612_FRAC_EXT: switch (write.addr>>8) { case 0: // port 0 w->writeC(2|baseAddr1); @@ -1148,6 +1152,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p break; case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612_EXT: + case DIV_SYSTEM_YM2612_FRAC: + case DIV_SYSTEM_YM2612_FRAC_EXT: if (!hasOPN2) { hasOPN2=disCont[i].dispatch->chipClock; willExport[i]=true; @@ -1796,6 +1802,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p switch (song.system[i]) { case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612_EXT: + case DIV_SYSTEM_YM2612_FRAC: + case DIV_SYSTEM_YM2612_FRAC_EXT: w->writeC(0x90); w->writeC(streamID); w->writeC(0x02); From 951cae4eecc2559f54fa96cdf1013bef847ebbfd Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 15:30:48 -0500 Subject: [PATCH 40/57] set SN volume to 32 when loading .dmf --- src/engine/fileOps.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/fileOps.cpp b/src/engine/fileOps.cpp index a13182e32..4b6e2f755 100644 --- a/src/engine/fileOps.cpp +++ b/src/engine/fileOps.cpp @@ -937,13 +937,13 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) { ds.systemLen=2; ds.system[0]=DIV_SYSTEM_YM2612; ds.system[1]=DIV_SYSTEM_SMS; - ds.systemVol[1]=24; + ds.systemVol[1]=32; } if (ds.system[0]==DIV_SYSTEM_GENESIS_EXT) { ds.systemLen=2; ds.system[0]=DIV_SYSTEM_YM2612_EXT; ds.system[1]=DIV_SYSTEM_SMS; - ds.systemVol[1]=24; + ds.systemVol[1]=32; } if (ds.system[0]==DIV_SYSTEM_ARCADE) { ds.systemLen=2; From 47fb434d5b5cbd49063b765818754e599dd13146 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 17 Oct 2022 16:12:10 -0500 Subject: [PATCH 41/57] GUI: update Genesis presets to be 32 --- src/gui/presets.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index e95b800db..beef25c83 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -527,35 +527,35 @@ void FurnaceGUI::initSystemPresets() { cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis", { DIV_SYSTEM_YM2612, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis (extended channel 3)", { DIV_SYSTEM_YM2612_EXT, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis (Fractal Sound template)", { DIV_SYSTEM_YM2612_FRAC, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis (Fractal Sound template, extended channel 3)", { DIV_SYSTEM_YM2612_FRAC_EXT, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis (with Sega CD)", { DIV_SYSTEM_YM2612, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, DIV_SYSTEM_RF5C68, 64, 0, 18, 0 } @@ -563,7 +563,7 @@ void FurnaceGUI::initSystemPresets() { cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis (extended channel 3 with Sega CD)", { DIV_SYSTEM_YM2612_EXT, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, DIV_SYSTEM_RF5C68, 64, 0, 18, 0 } @@ -2246,14 +2246,14 @@ void FurnaceGUI::initSystemPresets() { cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis", { DIV_SYSTEM_YM2612, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, 0 } )); cat.systems.push_back(FurnaceGUISysDef( "Sega Genesis (extended channel 3)", { DIV_SYSTEM_YM2612_EXT, 64, 0, 0, - DIV_SYSTEM_SMS, 24, 0, 0, + DIV_SYSTEM_SMS, 32, 0, 0, 0 } )); From 7486bb17f48a5bb7d2bb4a986531ec22891d7aed Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Oct 2022 13:14:52 -0500 Subject: [PATCH 42/57] GUI: fix wave edit randomize --- src/gui/waveEdit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 5509ca5b2..b678ad110 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -819,7 +819,7 @@ void FurnaceGUI::drawWaveEdit() { if (ImGui::Button("Randomize",buttonSize)) { if (wave->max>0) e->lockEngine([this,wave]() { for (int i=0; ilen; i++) { - wave->data[i]=rand()%wave->max; + wave->data[i]=rand()%(wave->max+1); } MARK_MODIFIED; }); From 206fb119aa0429348434a707942bc0573d062e61 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Oct 2022 13:48:29 -0500 Subject: [PATCH 43/57] VGM export: extended header length should be 12 --- src/engine/vgmOps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 3b2b87b39..f6de082a1 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -1567,7 +1567,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p unsigned int exHeaderOff=w->tell(); if (version>=0x170) { logD("writing extended header..."); - w->writeI(8); + w->writeI(12); w->writeI(0); w->writeI(4); From ca1118a40fae95f47d0c19fab3f0005a1fe437e2 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Oct 2022 13:53:56 -0500 Subject: [PATCH 44/57] GUI: fix crash in no asset menu (wave/sample) --- src/gui/sampleEdit.cpp | 5 ++++- src/gui/waveEdit.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index ac7845426..1d1b4e97f 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -60,7 +60,10 @@ void FurnaceGUI::drawSampleEdit() { if (e->song.sample.size()>0) { if (ImGui::BeginCombo("##SampleSelect","select one...")) { - actualSampleList(); + if (ImGui::BeginTable("SampleSelCombo",1,ImGuiTableFlags_ScrollY)) { + actualSampleList(); + ImGui::EndTable(); + } ImGui::EndCombo(); } ImGui::SameLine(); diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index b678ad110..41ac5cbf7 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -200,7 +200,10 @@ void FurnaceGUI::drawWaveEdit() { if (e->song.wave.size()>0) { if (ImGui::BeginCombo("##WaveSelect","select one...")) { - actualWaveList(); + if (ImGui::BeginTable("WaveSelCombo",1,ImGuiTableFlags_ScrollY)) { + actualWaveList(); + ImGui::EndTable(); + } ImGui::EndCombo(); } ImGui::SameLine(); From dc229078cc081cf09ac2794bd08eee1468decf4d Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Oct 2022 14:07:20 -0500 Subject: [PATCH 45/57] GUI: size constraints for effect list --- src/gui/effectList.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/effectList.cpp b/src/gui/effectList.cpp index 488d4e794..2c71b5671 100644 --- a/src/gui/effectList.cpp +++ b/src/gui/effectList.cpp @@ -9,6 +9,7 @@ void FurnaceGUI::drawEffectList() { nextWindow=GUI_WINDOW_NOTHING; } if (!effectListOpen) return; + ImGui::SetNextWindowSizeConstraints(ImVec2(60.0f*dpiScale,20.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); if (ImGui::Begin("Effect List",&effectListOpen,globalWinFlags)) { ImGui::Text("Chip at cursor: %s",e->getSystemName(e->sysOfChan[cursor.xCoarse])); if (ImGui::BeginTable("effectList",2)) { From 375d060f487d703eb1a5299845f81d3147a6d79b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Oct 2022 15:33:20 -0500 Subject: [PATCH 46/57] GUI: prepare for new HiDPI strategy --- src/gui/gui.cpp | 43 ++++++++++++++++++++++++++++++------------- src/gui/gui.h | 2 +- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index a66567ede..f3cc29181 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -5012,7 +5012,30 @@ bool FurnaceGUI::init() { e->setAutoNotePoly(noteInputPoly); + SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER,"1"); + SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS,"0"); + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS,"0"); + // don't disable compositing on KWin +#if SDL_VERSION_ATLEAST(2,0,22) + SDL_SetHint(SDL_HINT_X11_WINDOW_TYPE,"_NET_WM_WINDOW_TYPE_NORMAL"); +#endif + + // initialize SDL + SDL_Init(SDL_INIT_VIDEO); + + const char* videoBackend=SDL_GetCurrentVideoDriver(); + if (videoBackend!=NULL) { + if (strcmp(videoBackend,"wayland")==0 || + strcmp(videoBackend,"cocoa")==0 || + strcmp(videoBackend,"uikit")==0) { + sysManagedScale=true; + } + } + + // TODO: get scaling factor + #if !(defined(__APPLE__) || defined(_WIN32)) + // get the icon (on macOS and Windows the icon is bundled with the app) unsigned char* furIcon=getFurnaceIcon(); SDL_Surface* icon=SDL_CreateRGBSurfaceFrom(furIcon,256,256,32,256*4,0xff,0xff00,0xff0000,0xff000000); #endif @@ -5023,8 +5046,10 @@ bool FurnaceGUI::init() { scrX=0; scrY=0; #else - scrW=scrConfW=e->getConfInt("lastWindowWidth",1280); - scrH=scrConfH=e->getConfInt("lastWindowHeight",800); + double defaultW=1280*(sysManagedScale?1.0:dpiScale); + double defaultH=800*(sysManagedScale?1.0:dpiScale); + scrW=scrConfW=e->getConfInt("lastWindowWidth",(int)defaultW); + scrH=scrConfH=e->getConfInt("lastWindowHeight",(int)defaultH); scrX=scrConfX=e->getConfInt("lastWindowX",SDL_WINDOWPOS_CENTERED); scrY=scrConfY=e->getConfInt("lastWindowY",SDL_WINDOWPOS_CENTERED); scrMax=e->getConfBool("lastWindowMax",false); @@ -5036,16 +5061,6 @@ bool FurnaceGUI::init() { SDL_Rect displaySize; #endif - SDL_SetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER,"1"); - SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS,"0"); - SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS,"0"); - // don't disable compositing on KWin -#if SDL_VERSION_ATLEAST(2,0,22) - SDL_SetHint(SDL_HINT_X11_WINDOW_TYPE,"_NET_WM_WINDOW_TYPE_NORMAL"); -#endif - - SDL_Init(SDL_INIT_VIDEO); - #ifndef IS_MOBILE // if window would spawn out of bounds, force it to be get default position if (!detectOutOfBoundsWindow()) { @@ -5055,12 +5070,13 @@ bool FurnaceGUI::init() { } #endif - sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW*dpiScale,scrH*dpiScale,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); + sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW,scrH,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); if (sdlWin==NULL) { lastError=fmt::sprintf("could not open window! %s",SDL_GetError()); return false; } + // TODO: remove this #ifndef __APPLE__ if (settings.dpiScale<0.5f) { // TODO: replace with a function to actually detect the display scaling factor as it's unreliable. @@ -5358,6 +5374,7 @@ FurnaceGUI::FurnaceGUI(): scrConfX(SDL_WINDOWPOS_CENTERED), scrConfY(SDL_WINDOWPOS_CENTERED), scrMax(false), + sysManagedScale(false), dpiScale(1), aboutScroll(0), aboutSin(0), diff --git a/src/gui/gui.h b/src/gui/gui.h index fc47d6d8d..5f5064e53 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1064,7 +1064,7 @@ class FurnaceGUI { int scrW, scrH, scrConfW, scrConfH; int scrX, scrY, scrConfX, scrConfY; - bool scrMax; + bool scrMax, sysManagedScale; double dpiScale; From e365a92f65b480432833114b9bd3e7b0b04d871d Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 20 Oct 2022 11:44:48 +0900 Subject: [PATCH 47/57] Sync vgsound_emu with master --- extern/vgsound_emu-modified/CHANGELOG.md | 4 ++ extern/vgsound_emu-modified/CMakeLists.txt | 83 ++++++++++++++++++++-- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/extern/vgsound_emu-modified/CHANGELOG.md b/extern/vgsound_emu-modified/CHANGELOG.md index bf1e66771..305e83377 100644 --- a/extern/vgsound_emu-modified/CHANGELOG.md +++ b/extern/vgsound_emu-modified/CHANGELOG.md @@ -2,6 +2,10 @@ ## Important changes +### V 2.1.1 (2022-10-20) + +Add C++11 detection for CMake + ### V 2.1.0 (2022-09-08) Move source folder into vgsound_emu folder diff --git a/extern/vgsound_emu-modified/CMakeLists.txt b/extern/vgsound_emu-modified/CMakeLists.txt index 17e14291c..f1ba138e0 100644 --- a/extern/vgsound_emu-modified/CMakeLists.txt +++ b/extern/vgsound_emu-modified/CMakeLists.txt @@ -8,9 +8,11 @@ cmake_minimum_required(VERSION 3.0) project(vgsound_emu - VERSION 2.1.0 + VERSION 2.1.1 LANGUAGES CXX) +enable_language(CXX) + option(VGSOUND_EMU_ES5504 "Use ES5504 core" ON) option(VGSOUND_EMU_ES5505 "Use ES5505 core" ON) option(VGSOUND_EMU_ES5506 "Use ES5506 core" ON) @@ -31,19 +33,80 @@ message(STATUS "Generator: ${CMAKE_GENERATOR}") message(STATUS "Extra generator: ${CMAKE_EXTRA_GENERATOR}") message(STATUS "Make program: ${CMAKE_MAKE_PROGRAM}") +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.1.0") + message(STATUS "Generating C++11 compile features:") + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.8.0") + set(cxx_features cxx_std_11) + else() + set(cxx_features + cxx_template_template_parameters + cxx_alias_templates + cxx_alignas + cxx_alignof + cxx_attributes + cxx_auto_type + cxx_constexpr + cxx_decltype + cxx_decltype_incomplete_return_types + cxx_default_function_template_args + cxx_defaulted_functions + cxx_defaulted_move_initializers + cxx_delegating_constructors + cxx_deleted_functions + cxx_enum_forward_declarations + cxx_explicit_conversions + cxx_extended_friend_declarations + cxx_extern_templates + cxx_final + cxx_func_identifier + cxx_generalized_initializers + cxx_inheriting_constructors + cxx_inline_namespaces + cxx_lambdas + cxx_local_type_template_args + cxx_long_long_type + cxx_noexcept + cxx_nonstatic_member_init + cxx_nullptr + cxx_override + cxx_range_for + cxx_raw_string_literals + cxx_reference_qualified_functions + cxx_right_angle_brackets + cxx_rvalue_references + cxx_sizeof_member + cxx_static_assert + cxx_strong_enums + cxx_thread_local + cxx_trailing_return_types + cxx_unicode_literals + cxx_uniform_initialization + cxx_unrestricted_unions + cxx_user_literals + cxx_variadic_macros + cxx_variadic_templates) + endif() + + message(STATUS "${cxx_features}") +endif() + set(CORE_SOURCE "") set(EMU_SOURCE "") # Core functions list(APPEND CORE_SOURCE - vgsound_emu/src/core/util.hpp + vgsound_emu/src/core/core.hpp + vgsound_emu/src/core/util/clock_pulse.hpp + vgsound_emu/src/core/util/fifo.hpp + vgsound_emu/src/core/util/mem_intf.hpp ) # Dialogic ADPCM if(VGSOUND_EMU_MSM6295) list(APPEND CORE_SOURCE - vgsound_emu/src/core/vox/vox.cpp vgsound_emu/src/core/vox/vox.hpp + vgsound_emu/src/core/vox/vox.cpp ) message(STATUS "Using Dialogic ADPCM core") endif() @@ -156,6 +219,18 @@ if(VGSOUND_EMU_X1_010) endif() add_library(vgsound_emu STATIC ${CORE_SOURCE} ${EMU_SOURCE}) + +if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.1.0") + set_target_properties(vgsound_emu + PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON + CXX_EXTENSIONS OFF) + target_compile_features(vgsound_emu PRIVATE ${cxx_features}) + message(STATUS "C++11 Enabled") +endif() + target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) -# target_compile_options(vgsound_emu PRIVATE -Wall -Werror) \ No newline at end of file +# for Test purpose (GCC) +# target_compile_options(vgsound_emu PRIVATE -Wall -Wextra -Werror) \ No newline at end of file From 8e2f3199b54a8da441d69a296df450dc6921ca0e Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 20 Oct 2022 11:46:04 +0900 Subject: [PATCH 48/57] Sync this --- extern/vgsound_emu-modified/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/extern/vgsound_emu-modified/README.md b/extern/vgsound_emu-modified/README.md index b24e2888b..821147565 100644 --- a/extern/vgsound_emu-modified/README.md +++ b/extern/vgsound_emu-modified/README.md @@ -1,6 +1,6 @@ # vgsound_emu V2 (modified) -This is a library of video game sound chip emulation cores. useful for emulators, chiptune trackers, or players. +This is a C++ library of video game sound chip emulation cores. useful for emulators, chiptune trackers, or players. This is a modified version of vgsound_emu, tailored for Furnace. @@ -46,7 +46,8 @@ See [here](https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE) for detail ### dependencies -- CMake +- C++11 (or later) +- CMake (3.1 or later is recommended) - git (for source repository management) - MSVC or GCC or Clang (for compile) @@ -59,7 +60,7 @@ git clone https://gitlab.com/cam900/vgsound_emu.git cd vgsound_emu ``` -### Compile +### Compile with CMake #### MSVC From d96674186e555fcef0b18207e3546429f4b2e33c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 20 Oct 2022 01:49:33 -0500 Subject: [PATCH 49/57] GUI: new scaling factor detection technique --- CMakeLists.txt | 1 + src/engine/engine.h | 4 +- src/gui/gui.cpp | 122 ++++++++++++++++---------- src/gui/gui.h | 2 +- src/gui/scaling.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++++ src/gui/scaling.h | 20 +++++ 6 files changed, 306 insertions(+), 50 deletions(-) create mode 100644 src/gui/scaling.cpp create mode 100644 src/gui/scaling.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fc2d6dc75..8628379fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -593,6 +593,7 @@ src/gui/piano.cpp src/gui/presets.cpp src/gui/regView.cpp src/gui/sampleEdit.cpp +src/gui/scaling.cpp src/gui/settings.cpp src/gui/songInfo.cpp src/gui/songNotes.cpp diff --git a/src/engine/engine.h b/src/engine/engine.h index f4ed7cf5e..b30f52b1d 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -47,8 +47,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev121" -#define DIV_ENGINE_VERSION 121 +#define DIV_VERSION "dev122" +#define DIV_ENGINE_VERSION 122 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index f3cc29181..ec5e25cb3 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1,3 +1,5 @@ +#define _USE_MATH_DEFINES +// OK, sorry for inserting the define here but I'm so tired of this extension /** * Furnace Tracker - multi-system chiptune tracker * Copyright (C) 2021-2022 tildearrow and contributors @@ -20,7 +22,7 @@ // I hate you clangd extension! // how about you DON'T insert random headers before this freaking important // define!!!!!! -#define _USE_MATH_DEFINES + #include "gui.h" #include "util.h" #include "icon.h" @@ -36,17 +38,12 @@ #include "plot_nolerp.h" #include "guiConst.h" #include "intConst.h" +#include "scaling.h" #include #include #include #include -#ifdef __APPLE__ -extern "C" { -#include "macstuff.h" -} -#endif - #ifdef _WIN32 #include #include @@ -4898,9 +4895,7 @@ bool FurnaceGUI::loop() { } bool FurnaceGUI::init() { -#ifndef __APPLE__ - float dpiScaleF; -#endif + logI("initializing GUI."); String homeDir=getHomeDir(); workingDir=e->getConfString("lastDir",homeDir); @@ -5004,10 +4999,6 @@ bool FurnaceGUI::init() { } } - if (settings.dpiScale>=0.5f) { - dpiScale=settings.dpiScale; - } - initSystemPresets(); e->setAutoNotePoly(noteInputPoly); @@ -5017,6 +5008,7 @@ bool FurnaceGUI::init() { SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS,"0"); // don't disable compositing on KWin #if SDL_VERSION_ATLEAST(2,0,22) + logV("setting window type to NORMAL."); SDL_SetHint(SDL_HINT_X11_WINDOW_TYPE,"_NET_WM_WINDOW_TYPE_NORMAL"); #endif @@ -5025,14 +5017,28 @@ bool FurnaceGUI::init() { const char* videoBackend=SDL_GetCurrentVideoDriver(); if (videoBackend!=NULL) { + logV("video backend: %s",videoBackend); if (strcmp(videoBackend,"wayland")==0 || strcmp(videoBackend,"cocoa")==0 || strcmp(videoBackend,"uikit")==0) { sysManagedScale=true; + logV("scaling managed by system."); + } else { + logV("scaling managed by application."); } + } else { + logV("could not get video backend name!"); } - // TODO: get scaling factor + // get scale factor + if (settings.dpiScale>=0.5f) { + logD("setting UI scale factor from config (%f).",settings.dpiScale); + dpiScale=settings.dpiScale; + } else { + logD("auto-detecting UI scale factor."); + dpiScale=getScaleFactor(videoBackend); + logD("scale factor: %f",dpiScale); + } #if !(defined(__APPLE__) || defined(_WIN32)) // get the icon (on macOS and Windows the icon is bundled with the app) @@ -5046,10 +5052,8 @@ bool FurnaceGUI::init() { scrX=0; scrY=0; #else - double defaultW=1280*(sysManagedScale?1.0:dpiScale); - double defaultH=800*(sysManagedScale?1.0:dpiScale); - scrW=scrConfW=e->getConfInt("lastWindowWidth",(int)defaultW); - scrH=scrConfH=e->getConfInt("lastWindowHeight",(int)defaultH); + scrW=scrConfW=e->getConfInt("lastWindowWidth",1280); + scrH=scrConfH=e->getConfInt("lastWindowHeight",800); scrX=scrConfX=e->getConfInt("lastWindowX",SDL_WINDOWPOS_CENTERED); scrY=scrConfY=e->getConfInt("lastWindowY",SDL_WINDOWPOS_CENTERED); scrMax=e->getConfBool("lastWindowMax",false); @@ -5057,6 +5061,22 @@ bool FurnaceGUI::init() { portrait=(scrWgetConfInt("configVersion",0)<122 && !sysManagedScale) { + logD("scaling window size to scale factor because configVersion is not present."); + scrW*=dpiScale; + scrH*=dpiScale; + } + + // predict the canvas size + if (sysManagedScale) { + canvasW=scrW*dpiScale; + canvasH=scrH*dpiScale; + } else { + canvasW=scrW; + canvasH=scrH; + } + #if !defined(__APPLE__) && !defined(IS_MOBILE) SDL_Rect displaySize; #endif @@ -5070,47 +5090,41 @@ bool FurnaceGUI::init() { } #endif + logV("window size: %dx%d",scrW,scrH); + sdlWin=SDL_CreateWindow("Furnace",scrX,scrY,scrW,scrH,SDL_WINDOW_RESIZABLE|SDL_WINDOW_ALLOW_HIGHDPI|(scrMax?SDL_WINDOW_MAXIMIZED:0)|(fullScreen?SDL_WINDOW_FULLSCREEN_DESKTOP:0)); if (sdlWin==NULL) { lastError=fmt::sprintf("could not open window! %s",SDL_GetError()); return false; } - // TODO: remove this -#ifndef __APPLE__ - if (settings.dpiScale<0.5f) { - // TODO: replace with a function to actually detect the display scaling factor as it's unreliable. - SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(sdlWin),&dpiScaleF,NULL,NULL); - dpiScale=round(dpiScaleF/96.0f); - if (dpiScale<1) dpiScale=1; -#ifndef IS_MOBILE - if (dpiScale!=1) { - if (!fullScreen) { - SDL_SetWindowSize(sdlWin,scrW*dpiScale,scrH*dpiScale); - } + if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) { + bool mustChange=false; + if (scrW>((displaySize.w)-48) && scrH>((displaySize.h)-64)) { + // maximize + SDL_MaximizeWindow(sdlWin); + logD("maximizing as it doesn't fit (%dx%d+%d+%d).",displaySize.w,displaySize.h,displaySize.x,displaySize.y); } - - if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) { - if (scrW>((displaySize.w/dpiScale)-48) && scrH>((displaySize.h/dpiScale)-64)) { - // maximize - SDL_MaximizeWindow(sdlWin); - } - if (scrW>displaySize.w/dpiScale) scrW=(displaySize.w/dpiScale)-32; - if (scrH>displaySize.h/dpiScale) scrH=(displaySize.h/dpiScale)-32; + if (scrW>displaySize.w) { + scrW=(displaySize.w)-32; + mustChange=true; + } + if (scrH>displaySize.h) { + scrH=(displaySize.h)-32; + mustChange=true; + } + if (mustChange) { portrait=(scrWsetConf("configVersion",(int)DIV_ENGINE_VERSION); + e->setConf("lastDir",workingDir); e->setConf("lastDirSong",workingDirSong); e->setConf("lastDirIns",workingDirIns); @@ -5369,6 +5395,8 @@ FurnaceGUI::FurnaceGUI(): scrH(800), scrConfW(1280), scrConfH(800), + canvasW(1280), + canvasH(800), scrX(SDL_WINDOWPOS_CENTERED), scrY(SDL_WINDOWPOS_CENTERED), scrConfX(SDL_WINDOWPOS_CENTERED), diff --git a/src/gui/gui.h b/src/gui/gui.h index 5f5064e53..dd3a02af5 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1062,7 +1062,7 @@ class FurnaceGUI { FurnaceGUIFileDialog* fileDialog; - int scrW, scrH, scrConfW, scrConfH; + int scrW, scrH, scrConfW, scrConfH, canvasW, canvasH; int scrX, scrY, scrConfX, scrConfY; bool scrMax, sysManagedScale; diff --git a/src/gui/scaling.cpp b/src/gui/scaling.cpp new file mode 100644 index 000000000..c1fd5bccd --- /dev/null +++ b/src/gui/scaling.cpp @@ -0,0 +1,207 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 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 +#include "scaling.h" +#include "../ta-log.h" +#include + +#ifdef _WIN32 +#include +typedef HRESULT (*GDFM)(HMONITOR,int,UINT*,UINT*); +#endif + +#ifdef __APPLE__ +extern "C" { +#include "macstuff.h" +} +#endif + +#if defined(__unix__) || defined(ANDROID) +#include +typedef void* (*XOD)(const char*); +typedef int (*XCD)(void*); +typedef int (*XDS)(void*); +typedef int (*XDW)(void*,int); +#endif + +double getScaleFactor(const char* driverHint) { + double ret=1.0; + + // Windows +#ifdef _WIN32 + POINT nullPoint; + nullPoint.x=-1; + nullPoint.y=-1; + HMONITOR disp=MonitorFromPoint(nullPoint,MONITOR_DEFAULTTOPRIMARY); + + if (disp==NULL) { + logW("could not find a monitor - no scaling detection available!"); + return 1.0; + } + + HMODULE shcore=LoadLibraryW(L"shcore.dll"); + if (shcore==NULL) { + logW("could not find shcore.dll (%.8x) - no scaling detection available!",GetLastError()); + return 1.0; + } + GDFM ta_GetDpiForMonitor=(GDFM)GetProcAddress(shcore,"GetDpiForMonitor"); + if (ta_GetDpiForMonitor==NULL) { + logW("GetDpiForMonitor not found (%.8x) - no scaling detection available!",GetLastError()); + + if (!FreeLibrary(shcore)) { + logE("could not free shcore.dll (%.8x)!",GetLastError()); + } + return 1.0; + } + + unsigned int dpiX=96; + unsigned int dpiY=96; + HRESULT result=ta_GetDpiForMonitor(disp,0,&dpiX,&dpiY); + if (result!=S_OK) { + logW("GetDpiForMonitor failure (%.8x) - no scaling detection available!",result); + + if (!FreeLibrary(shcore)) { + logE("could not free shcore.dll (%.8x)!",GetLastError()); + } + return 1.0; + } + + ret=(double)(dpiX+dpiY)/192.0; + + if (!FreeLibrary(shcore)) { + logE("could not free shcore.dll (%.8x)!",GetLastError()); + } + + return ret; +#endif + + // macOS - backingScaleFactor +#ifdef __APPLE__ + if (driverHint==NULL) { + return getMacDPIScale(); + } else if (strcmp(driverHint,"cocoa")==0 || strcmp(driverHint,"uikit")==0) { + return getMacDPIScale(); + } +#endif + +#if defined(__unix__) || defined(ANDROID) + if (driverHint==NULL) { + return ret; + } + + // X11 + if (strcmp(driverHint,"x11")==0) { + void* libX11=dlopen("libX11.so",RTLD_LAZY|RTLD_LOCAL); + if (libX11==NULL) { + logW("could not load libX11.so (%s) - no scaling detection available!",dlerror()); + return 1.0; + } + + XOD ta_XOpenDisplay=(XOD)dlsym(libX11,"XOpenDisplay"); + if (ta_XOpenDisplay==NULL) { + logW("XOpenDisplay not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XCD ta_XCloseDisplay=(XCD)dlsym(libX11,"XCloseDisplay"); + if (ta_XCloseDisplay==NULL) { + logW("XCloseDisplay not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XDS ta_XDefaultScreen=(XDS)dlsym(libX11,"XDefaultScreen"); + if (ta_XDefaultScreen==NULL) { + logW("XDefaultScreen not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XDW ta_XDisplayWidth=(XDW)dlsym(libX11,"XDisplayWidth"); + if (ta_XDisplayWidth==NULL) { + logW("XDisplayWidth not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + XDW ta_XDisplayWidthMM=(XDW)dlsym(libX11,"XDisplayWidthMM"); + if (ta_XDisplayWidthMM==NULL) { + logW("XDisplayWidthMM not found (%s) - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + // dl mess + void* disp=NULL; + int screen=0; + int dpi=96; + + disp=ta_XOpenDisplay(NULL); + if (disp==NULL) { + logW("couldn't open X display - no scaling detection available!",dlerror()); + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + return 1.0; + } + + screen=ta_XDefaultScreen(disp); + + dpi=(int)(0.5+(25.4*(double)ta_XDisplayWidth(disp,screen)/(double)ta_XDisplayWidthMM(disp,screen))); + + ta_XCloseDisplay(disp); + + ret=round(dpi/96.0); + + if (dlclose(libX11)!=0) { + logE("could not free libX11.so (%s)!",dlerror()); + } + + return ret; + } + + // Wayland + if (strcmp(driverHint,"wayland")==0) { + // give up (we handle scaling factor detection after window creation) + return 1.0; + } +#endif + + // SDL fallback + float dpiScaleF=96.0f; + if (SDL_GetDisplayDPI(0,&dpiScaleF,NULL,NULL)==0) { + ret=round(dpiScaleF/96.0f); + if (ret<1) ret=1; + } + + // couldn't detect scaling factor :< + return ret; +} diff --git a/src/gui/scaling.h b/src/gui/scaling.h new file mode 100644 index 000000000..ce1a364a6 --- /dev/null +++ b/src/gui/scaling.h @@ -0,0 +1,20 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 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. + */ + +double getScaleFactor(const char* driverHint); \ No newline at end of file From 373367724b4edefa00cf14bf3f498d70824520df Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 20 Oct 2022 02:34:14 -0500 Subject: [PATCH 50/57] GUI: use canvasW/H instead of scrW/H*dpiScale --- src/gui/about.cpp | 39 ++++++++++++---------------- src/gui/chanOsc.cpp | 2 +- src/gui/debugWindow.cpp | 2 +- src/gui/editControls.cpp | 8 +++--- src/gui/effectList.cpp | 2 +- src/gui/findReplace.cpp | 2 +- src/gui/gui.cpp | 56 +++++++++++++++++----------------------- src/gui/insEdit.cpp | 6 ++--- src/gui/mixer.cpp | 2 +- src/gui/osc.cpp | 2 +- src/gui/pattern.cpp | 4 +-- src/gui/piano.cpp | 2 +- src/gui/sampleEdit.cpp | 4 +-- src/gui/subSongs.cpp | 2 +- src/gui/volMeter.cpp | 2 +- src/gui/waveEdit.cpp | 6 ++--- 16 files changed, 63 insertions(+), 78 deletions(-) diff --git a/src/gui/about.cpp b/src/gui/about.cpp index 99a279268..809cd1a3d 100644 --- a/src/gui/about.cpp +++ b/src/gui/about.cpp @@ -23,18 +23,13 @@ const char* aboutLine[]={ "tildearrow", - "is not so happy to present", + "is proud to present", "", ("Furnace " DIV_VERSION), "", "the biggest multi-system chiptune tracker!", "featuring DefleMask song compatibility.", "", - "what a mess of a versioning scheme we have...", - "I mean it! these pre-releases are like normal releases", - "by now but only because I promised you to have SNES in", - "0.6pre2 I am doing this whole mess...", - "", "> CREDITS <", "", "-- program --", @@ -187,7 +182,7 @@ void FurnaceGUI::drawAbout() { // do stuff if (ImGui::Begin("About Furnace",NULL,ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoDocking|ImGuiWindowFlags_NoTitleBar)) { ImGui::SetWindowPos(ImVec2(0,0)); - ImGui::SetWindowSize(ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetWindowSize(ImVec2(canvasW,canvasH)); ImGui::PushFont(bigFont); ImDrawList* dl=ImGui::GetWindowDrawList(); float r=0; @@ -195,47 +190,47 @@ void FurnaceGUI::drawAbout() { float b=0; float peakMix=settings.partyTime?((peak[0]+peak[1])*0.5):0.3; ImGui::ColorConvertHSVtoRGB(aboutHue,1.0,0.25+MIN(0.75f,peakMix*0.75f),r,g,b); - dl->AddRectFilled(ImVec2(0,0),ImVec2(scrW*dpiScale,scrH*dpiScale),0xff000000); + dl->AddRectFilled(ImVec2(0,0),ImVec2(canvasW,canvasH),0xff000000); bool skip=false; bool skip2=false; - for (int i=(-80-sin(double(aboutSin)*2*M_PI/120.0)*80.0)*2; iAddRectFilled(ImVec2(i*dpiScale,j*dpiScale),ImVec2((i+160)*dpiScale,(j+160)*dpiScale),ImGui::GetColorU32(ImVec4(r*0.25,g*0.25,b*0.25,1.0))); + dl->AddRectFilled(ImVec2(i,j),ImVec2(i+160*dpiScale,j+160*dpiScale),ImGui::GetColorU32(ImVec4(r*0.25,g*0.25,b*0.25,1.0))); } } skip=false; skip2=false; - for (int i=(-80-cos(double(aboutSin)*2*M_PI/120.0)*80.0)*2; iAddRectFilled(ImVec2(i*dpiScale,j*dpiScale),ImVec2((i+160)*dpiScale,(j+160)*dpiScale),ImGui::GetColorU32(ImVec4(r*0.5,g*0.5,b*0.5,1.0))); + dl->AddRectFilled(ImVec2(i,j),ImVec2(i+160*dpiScale,j+160*dpiScale),ImGui::GetColorU32(ImVec4(r*0.5,g*0.5,b*0.5,1.0))); } } skip=false; skip2=false; - for (int i=(-160+fmod(aboutSin*2,160))*2; iAddRectFilled(ImVec2(i*dpiScale,j*dpiScale),ImVec2((i+160)*dpiScale,(j+160)*dpiScale),ImGui::GetColorU32(ImVec4(r*0.75,g*0.75,b*0.75,1.0))); + dl->AddRectFilled(ImVec2(i,j),ImVec2(i+160*dpiScale,j+160*dpiScale),ImGui::GetColorU32(ImVec4(r*0.75,g*0.75,b*0.75,1.0))); } } for (size_t i=0; iscrH*dpiScale) continue; + double posX=(canvasW/2.0)+(sin(double(i)*0.5+double(aboutScroll)/(90.0*dpiScale))*120*dpiScale)-(ImGui::CalcTextSize(aboutLine[i]).x*0.5); + double posY=(canvasH-aboutScroll+42*i*dpiScale); + if (posY<-80*dpiScale || posY>canvasH) continue; dl->AddText(bigFont,bigFont->FontSize, ImVec2(posX+dpiScale,posY+dpiScale), 0xff000000,aboutLine[i]); @@ -257,12 +252,12 @@ void FurnaceGUI::drawAbout() { float timeScale=60.0f*ImGui::GetIO().DeltaTime; aboutHue+=(0.001+peakMix*0.004)*timeScale; - aboutScroll+=(2+(peakMix>0.78)*3)*timeScale; + aboutScroll+=(2+(peakMix>0.78)*3)*timeScale*dpiScale; aboutSin+=(1+(peakMix>0.75)*2)*timeScale; while (aboutHue>1) aboutHue--; while (aboutSin>=2400) aboutSin-=2400; - if (aboutScroll>(42*aboutCount+scrH)) aboutScroll=-20; + if (aboutScroll>(42*dpiScale*aboutCount+canvasH)) aboutScroll=-20*dpiScale; WAKE_UP; } diff --git a/src/gui/chanOsc.cpp b/src/gui/chanOsc.cpp index 89b89801b..851ca6ede 100644 --- a/src/gui/chanOsc.cpp +++ b/src/gui/chanOsc.cpp @@ -109,7 +109,7 @@ void FurnaceGUI::drawChanOsc() { nextWindow=GUI_WINDOW_NOTHING; } if (!chanOscOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Oscilloscope (per-channel)",&chanOscOpen,globalWinFlags|((chanOscOptions)?0:ImGuiWindowFlags_NoTitleBar))) { bool centerSettingReset=false; ImDrawList* dl=ImGui::GetWindowDrawList(); diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index 38275c74c..68130d9dc 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -42,7 +42,7 @@ void FurnaceGUI::drawDebug() { nextWindow=GUI_WINDOW_NOTHING; } if (!debugOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Debug",&debugOpen,globalWinFlags|ImGuiWindowFlags_NoDocking)) { ImGui::Text("NOTE: use with caution."); if (ImGui::TreeNode("Debug Controls")) { diff --git a/src/gui/editControls.cpp b/src/gui/editControls.cpp index 1d0e2a250..e3e348c14 100644 --- a/src/gui/editControls.cpp +++ b/src/gui/editControls.cpp @@ -38,8 +38,8 @@ void FurnaceGUI::drawMobileControls() { mobileMenuPos=0.0f; } } - ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*scrH*dpiScale)-(0.16*scrW*dpiScale)):ImVec2(0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - ImGui::SetNextWindowSize(portrait?ImVec2(scrW*dpiScale,0.16*scrW*dpiScale):ImVec2(0.16*scrH*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*canvasH)-(0.16*canvasW)):ImVec2(0.5*canvasW*mobileMenuPos,0.0f)); + ImGui::SetNextWindowSize(portrait?ImVec2(canvasW,0.16*canvasW):ImVec2(0.16*canvasH,canvasH)); if (ImGui::Begin("Mobile Controls",NULL,ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|globalWinFlags)) { float avail=portrait?ImGui::GetContentRegionAvail().y:ImGui::GetContentRegionAvail().x; ImVec2 buttonSize=ImVec2(avail,avail); @@ -101,8 +101,8 @@ void FurnaceGUI::drawMobileControls() { if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows)) curWindow=GUI_WINDOW_EDIT_CONTROLS; ImGui::End(); - ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*scrH*dpiScale)):ImVec2(0.5*scrW*dpiScale*(mobileMenuPos-1.0),0.0f)); - ImGui::SetNextWindowSize(portrait?ImVec2(scrW*dpiScale,0.65*scrH*dpiScale):ImVec2(0.5*scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*canvasH)):ImVec2(0.5*canvasW*(mobileMenuPos-1.0),0.0f)); + ImGui::SetNextWindowSize(portrait?ImVec2(canvasW,0.65*canvasH):ImVec2(0.5*canvasW,canvasH)); if (ImGui::Begin("Mobile Menu",NULL,ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|globalWinFlags)) { if (ImGui::BeginTable("SceneSel",5)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthStretch,1.0f); diff --git a/src/gui/effectList.cpp b/src/gui/effectList.cpp index 2c71b5671..604204b86 100644 --- a/src/gui/effectList.cpp +++ b/src/gui/effectList.cpp @@ -9,7 +9,7 @@ void FurnaceGUI::drawEffectList() { nextWindow=GUI_WINDOW_NOTHING; } if (!effectListOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(60.0f*dpiScale,20.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(60.0f*dpiScale,20.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Effect List",&effectListOpen,globalWinFlags)) { ImGui::Text("Chip at cursor: %s",e->getSystemName(e->sysOfChan[cursor.xCoarse])); if (ImGui::BeginTable("effectList",2)) { diff --git a/src/gui/findReplace.cpp b/src/gui/findReplace.cpp index 428fce5a4..91b494210 100644 --- a/src/gui/findReplace.cpp +++ b/src/gui/findReplace.cpp @@ -494,7 +494,7 @@ void FurnaceGUI::drawFindReplace() { nextWindow=GUI_WINDOW_NOTHING; } if (!findOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Find/Replace",&findOpen,globalWinFlags)) { if (curQuery.empty()) { curQuery.push_back(FurnaceGUIFindQuery()); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index ec5e25cb3..45c4f018b 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2751,12 +2751,8 @@ void FurnaceGUI::processPoint(SDL_Event& ev) { TouchPoint* point=NULL; FIND_POINT(point,-1); if (point!=NULL) { - point->x=ev.motion.x; - point->y=ev.motion.y; -#ifdef __APPLE__ - point->x*=dpiScale; - point->y*=dpiScale; -#endif + point->x=(double)ev.motion.x*((double)canvasW/(double)scrW); + point->y=(double)ev.motion.y*((double)canvasH/(double)scrH); } break; } @@ -2797,8 +2793,8 @@ void FurnaceGUI::processPoint(SDL_Event& ev) { if (point!=NULL) { float prevX=point->x; float prevY=point->y; - point->x=ev.tfinger.x*scrW*dpiScale; - point->y=ev.tfinger.y*scrH*dpiScale; + point->x=ev.tfinger.x*canvasW; + point->y=ev.tfinger.y*canvasH; point->z=ev.tfinger.pressure; if (point->id==0) { @@ -2817,7 +2813,7 @@ void FurnaceGUI::processPoint(SDL_Event& ev) { break; } } - TouchPoint newPoint(ev.tfinger.fingerId,ev.tfinger.x*scrW*dpiScale,ev.tfinger.y*scrH*dpiScale,ev.tfinger.pressure); + TouchPoint newPoint(ev.tfinger.fingerId,ev.tfinger.x*canvasW,ev.tfinger.y*canvasH,ev.tfinger.pressure); activePoints.push_back(newPoint); pressedPoints.push_back(newPoint); @@ -2983,16 +2979,10 @@ bool FurnaceGUI::loop() { if (!doThreadedInput) processEvent(&ev); switch (ev.type) { case SDL_MOUSEMOTION: { - int motionX=ev.motion.x; - int motionY=ev.motion.y; - int motionXrel=ev.motion.xrel; - int motionYrel=ev.motion.yrel; -#ifdef __APPLE__ - motionX*=dpiScale; - motionY*=dpiScale; - motionXrel*=dpiScale; - motionYrel*=dpiScale; -#endif + int motionX=(double)ev.motion.x*((double)canvasW/(double)scrW); + int motionY=(double)ev.motion.y*((double)canvasH/(double)scrH); + int motionXrel=(double)ev.motion.xrel*((double)canvasW/(double)scrW); + int motionYrel=(double)ev.motion.yrel*((double)canvasH/(double)scrH); pointMotion(motionX,motionY,motionXrel,motionYrel); break; } @@ -3009,13 +2999,8 @@ bool FurnaceGUI::loop() { case SDL_WINDOWEVENT: switch (ev.window.event) { case SDL_WINDOWEVENT_RESIZED: -#ifdef __APPLE__ scrW=ev.window.data1; scrH=ev.window.data2; -#else - scrW=ev.window.data1/dpiScale; - scrH=ev.window.data2/dpiScale; -#endif portrait=(scrWAddRectFilled(ImVec2(0.0f,0.0f),ImVec2(scrW*dpiScale,scrH*dpiScale),ImGui::ColorConvertFloat4ToU32(uiColors[GUI_COLOR_MODAL_BACKDROP])); + dl->AddRectFilled(ImVec2(0.0f,0.0f),ImVec2(canvasW,canvasH),ImGui::ColorConvertFloat4ToU32(uiColors[GUI_COLOR_MODAL_BACKDROP])); ImGui::EndPopup(); } #endif - if (fileDialog->render(ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) { + if (fileDialog->render(ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(canvasW,canvasH))) { bool openOpen=false; //ImGui::GetIO().ConfigFlags&=~ImGuiConfigFlags_NavEnableKeyboard; if ((curFileDialog==GUI_FILE_INS_OPEN || curFileDialog==GUI_FILE_INS_OPEN_REPLACE) && prevIns!=-3) { @@ -4345,9 +4333,9 @@ bool FurnaceGUI::loop() { ImGui::EndPopup(); } - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::BeginPopupModal("New Song",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) { - ImGui::SetWindowPos(ImVec2(((scrW*dpiScale)-ImGui::GetWindowSize().x)*0.5,((scrH*dpiScale)-ImGui::GetWindowSize().y)*0.5)); + ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5)); drawNewSong(); ImGui::EndPopup(); } @@ -4715,8 +4703,8 @@ bool FurnaceGUI::loop() { } bool anySelected=false; float sizeY=ImGui::GetFrameHeightWithSpacing()*pendingIns.size(); - if (sizeY>(scrH-180.0)*dpiScale) { - sizeY=(scrH-180.0)*dpiScale; + if (sizeY>(canvasH-180.0*dpiScale)) { + sizeY=canvasH-180.0*dpiScale; if (sizeY<60.0*dpiScale) sizeY=60.0*dpiScale; } if (ImGui::BeginTable("PendingInsList",1,ImGuiTableFlags_ScrollY,ImVec2(0.0f,sizeY))) { @@ -5077,7 +5065,7 @@ bool FurnaceGUI::init() { canvasH=scrH; } -#if !defined(__APPLE__) && !defined(IS_MOBILE) +#ifndef IS_MOBILE SDL_Rect displaySize; #endif @@ -5098,6 +5086,7 @@ bool FurnaceGUI::init() { return false; } +#ifndef IS_MOBILE if (SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(sdlWin),&displaySize)==0) { bool mustChange=false; if (scrW>((displaySize.w)-48) && scrH>((displaySize.h)-64)) { @@ -5122,6 +5111,7 @@ bool FurnaceGUI::init() { } } } +#endif #ifdef IS_MOBILE SDL_GetWindowSize(sdlWin,&scrW,&scrH); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 8cfbf9ec5..2894f4346 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -1903,12 +1903,12 @@ void FurnaceGUI::drawInsEdit() { } if (!insEditOpen) return; if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } else { - ImGui::SetNextWindowSizeConstraints(ImVec2(440.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(440.0f*dpiScale,400.0f*dpiScale),ImVec2(canvasW,canvasH)); } if (ImGui::Begin("Instrument Editor",&insEditOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { if (curIns<0 || curIns>=(int)e->song.ins.size()) { diff --git a/src/gui/mixer.cpp b/src/gui/mixer.cpp index 4897c64ac..019336ae4 100644 --- a/src/gui/mixer.cpp +++ b/src/gui/mixer.cpp @@ -27,7 +27,7 @@ void FurnaceGUI::drawMixer() { nextWindow=GUI_WINDOW_NOTHING; } if (!mixerOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(400.0f*dpiScale,200.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Mixer",&mixerOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { char id[32]; if (ImGui::SliderFloat("Master Volume",&e->song.masterVol,0,3,"%.2fx")) { diff --git a/src/gui/osc.cpp b/src/gui/osc.cpp index 176d7d54f..7791e8e56 100644 --- a/src/gui/osc.cpp +++ b/src/gui/osc.cpp @@ -84,7 +84,7 @@ void FurnaceGUI::drawOsc() { nextWindow=GUI_WINDOW_NOTHING; } if (!oscOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (settings.oscTakesEntireWindow) { ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0)); diff --git a/src/gui/pattern.cpp b/src/gui/pattern.cpp index 385441d42..00e9b5106 100644 --- a/src/gui/pattern.cpp +++ b/src/gui/pattern.cpp @@ -376,8 +376,8 @@ void FurnaceGUI::drawPattern() { } ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0.0f,0.0f)); if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } diff --git a/src/gui/piano.cpp b/src/gui/piano.cpp index 082cc65e9..c0664e987 100644 --- a/src/gui/piano.cpp +++ b/src/gui/piano.cpp @@ -54,7 +54,7 @@ void FurnaceGUI::drawPiano() { if (!pianoOpen) return; if (mobileUI) { ImGui::SetNextWindowPos(ImVec2(patWindowPos.x,patWindowPos.y+patWindowSize.y)); - ImGui::SetNextWindowSize(portrait?ImVec2(scrW*dpiScale,0.4*scrW*dpiScale):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),0.3*scrH*dpiScale)); + ImGui::SetNextWindowSize(portrait?ImVec2(canvasW,0.4*canvasW):ImVec2(canvasW-(0.16*canvasH),0.3*canvasH)); } if (ImGui::Begin("Piano",&pianoOpen,((pianoOptions)?0:ImGuiWindowFlags_NoTitleBar)|ImGuiWindowFlags_NoScrollbar|ImGuiWindowFlags_NoScrollWithMouse|globalWinFlags)) { bool oldPianoKeyPressed[180]; diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index 1d1b4e97f..2dc12ad56 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -39,8 +39,8 @@ void FurnaceGUI::drawSampleEdit() { } if (!sampleEditOpen) return; if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } diff --git a/src/gui/subSongs.cpp b/src/gui/subSongs.cpp index f076298f2..a6eb70f0b 100644 --- a/src/gui/subSongs.cpp +++ b/src/gui/subSongs.cpp @@ -11,7 +11,7 @@ void FurnaceGUI::drawSubSongs() { nextWindow=GUI_WINDOW_NOTHING; } if (!subSongsOpen) return; - ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(64.0f*dpiScale,32.0f*dpiScale),ImVec2(canvasW,canvasH)); if (ImGui::Begin("Subsongs",&subSongsOpen,globalWinFlags)) { char id[1024]; ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x-ImGui::GetFrameHeightWithSpacing()*2.0f-ImGui::GetStyle().ItemSpacing.x); diff --git a/src/gui/volMeter.cpp b/src/gui/volMeter.cpp index 7f68709c4..d058e31f7 100644 --- a/src/gui/volMeter.cpp +++ b/src/gui/volMeter.cpp @@ -28,7 +28,7 @@ void FurnaceGUI::drawVolMeter() { } if (!volMeterOpen) return; if (--isClipping<0) isClipping=0; - ImGui::SetNextWindowSizeConstraints(ImVec2(6.0f*dpiScale,6.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(6.0f*dpiScale,6.0f*dpiScale),ImVec2(canvasW,canvasH)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0,0)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(0,0)); diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index 41ac5cbf7..4054a66b9 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -177,12 +177,12 @@ void FurnaceGUI::drawWaveEdit() { if (!waveEditOpen) return; float wavePreview[257]; if (mobileUI) { - patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*scrH*dpiScale)):ImVec2((0.16*scrH*dpiScale)+0.5*scrW*dpiScale*mobileMenuPos,0.0f)); - patWindowSize=(portrait?ImVec2(scrW*dpiScale,scrH*dpiScale-(0.16*scrW*dpiScale)-(pianoOpen?(0.4*scrW*dpiScale):0.0f)):ImVec2(scrW*dpiScale-(0.16*scrH*dpiScale),scrH*dpiScale-(pianoOpen?(0.3*scrH*dpiScale):0.0f))); + patWindowPos=(portrait?ImVec2(0.0f,(mobileMenuPos*-0.65*canvasH)):ImVec2((0.16*canvasH)+0.5*canvasW*mobileMenuPos,0.0f)); + patWindowSize=(portrait?ImVec2(canvasW,canvasH-(0.16*canvasW)-(pianoOpen?(0.4*canvasW):0.0f)):ImVec2(canvasW-(0.16*canvasH),canvasH-(pianoOpen?(0.3*canvasH):0.0f))); ImGui::SetNextWindowPos(patWindowPos); ImGui::SetNextWindowSize(patWindowSize); } else { - ImGui::SetNextWindowSizeConstraints(ImVec2(300.0f*dpiScale,300.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale)); + ImGui::SetNextWindowSizeConstraints(ImVec2(300.0f*dpiScale,300.0f*dpiScale),ImVec2(canvasW,canvasH)); } if (ImGui::Begin("Wavetable Editor",&waveEditOpen,globalWinFlags|(settings.allowEditDocking?0:ImGuiWindowFlags_NoDocking))) { if (curWave<0 || curWave>=(int)e->song.wave.size()) { From c6e21e3da5daf56b8b5184bfe37b440ee7fa4d7f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 20 Oct 2022 02:49:08 -0500 Subject: [PATCH 51/57] GUI: fix input scaling --- .../imgui_patched/backends/imgui_impl_sdl.cpp | 54 +++++++------------ 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/extern/imgui_patched/backends/imgui_impl_sdl.cpp b/extern/imgui_patched/backends/imgui_impl_sdl.cpp index 2424dd41a..e7ae8d072 100644 --- a/extern/imgui_patched/backends/imgui_impl_sdl.cpp +++ b/extern/imgui_patched/backends/imgui_impl_sdl.cpp @@ -276,9 +276,6 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) case SDL_MOUSEMOTION: { ImVec2 mouse_pos((float)event->motion.x, (float)event->motion.y); -#ifdef __APPLE__ - -#endif if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { int window_x, window_y; @@ -286,16 +283,14 @@ bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event) mouse_pos.x += window_x; mouse_pos.y += window_y; } -#ifdef __APPLE__ - // Fix for high DPI mac - ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) - { - // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! - mouse_pos.x *= std::ceil(platform_io.Monitors[0].DpiScale); - mouse_pos.y *= std::ceil(platform_io.Monitors[0].DpiScale); - } -#endif + // Fix for high DPI mac/idevice/wayland + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) + { + // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! + mouse_pos.x *= std::ceil(platform_io.Monitors[0].DpiScale); + mouse_pos.y *= std::ceil(platform_io.Monitors[0].DpiScale); + } io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); return true; } @@ -551,16 +546,14 @@ static void ImGui_ImplSDL2_UpdateMouseData() mouse_x -= window_x; mouse_y -= window_y; } -#ifdef __APPLE__ - // Fix for high DPI mac - ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) - { - // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! - mouse_x *= std::ceil(platform_io.Monitors[0].DpiScale); - mouse_y *= std::ceil(platform_io.Monitors[0].DpiScale); - } -#endif + // Fix for high DPI mac/idevice/wayland + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f) + { + // The Framebuffer is scaled by an integer ceiling of the actual ratio, so 2.0 not 1.685 on Mac! + mouse_x *= std::ceil(platform_io.Monitors[0].DpiScale); + mouse_y *= std::ceil(platform_io.Monitors[0].DpiScale); + } io.AddMousePosEvent((float)mouse_x, (float)mouse_y); } } @@ -669,13 +662,7 @@ static void ImGui_ImplSDL2_UpdateMonitors() monitor.WorkSize = ImVec2((float)r.w, (float)r.h); #endif #if SDL_HAS_PER_MONITOR_DPI -#ifdef __APPLE__ - monitor.DpiScale=getMacDPIScale(); -#else - float dpi = 0.0f; - if (!SDL_GetDisplayDPI(n, &dpi, NULL, NULL)) - monitor.DpiScale = dpi / 96.0f; -#endif + monitor.DpiScale = 1.0f; #endif platform_io.Monitors.push_back(monitor); } @@ -701,15 +688,14 @@ void ImGui_ImplSDL2_NewFrame() if (w > 0 && h > 0) io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); -#if defined(__APPLE__) - // On Apple, The window size is reported in Low DPI, even when running in high DPI mode + // On Apple and Wayland, The window size is reported in Low DPI, even when running in high DPI mode ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - if (!platform_io.Monitors.empty() && platform_io.Monitors[0].DpiScale > 1.0f && display_h != h) + if (!platform_io.Monitors.empty() /*&& platform_io.Monitors[0].DpiScale > 1.0f*/ && display_h != h) { io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f); io.DisplaySize = ImVec2((float)display_w, (float)display_h); + platform_io.Monitors[0].DpiScale=(float)display_w/(float)w; } -#endif // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) static Uint64 frequency = SDL_GetPerformanceFrequency(); From bfeb57c3b77d6d97e222c0028cb17062ee5b134a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 20 Oct 2022 02:55:24 -0500 Subject: [PATCH 52/57] we don't have to work around Wayland issue anymore --- src/main.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e0a63dd71..8c3890f16 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -332,12 +332,6 @@ int main(int argc, char** argv) { if (coResult!=S_OK) { logE("CoInitializeEx failed!"); } -#endif -#if !(defined(__APPLE__) || defined(_WIN32) || defined(ANDROID) || defined(__HAIKU__)) - // workaround for Wayland HiDPI issue - if (getenv("SDL_VIDEODRIVER")==NULL) { - setenv("SDL_VIDEODRIVER","x11",1); - } #endif outName=""; vgmOutName=""; From 3de0e6bc9f886466ff1c4dad317a9d4cd2c8acb5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 20 Oct 2022 03:34:12 -0500 Subject: [PATCH 53/57] SetProcessDpiAwareness --- src/winMain.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/winMain.cpp b/src/winMain.cpp index 69034b9ff..853b11530 100644 --- a/src/winMain.cpp +++ b/src/winMain.cpp @@ -19,6 +19,8 @@ #include "utfutils.h" +typedef HRESULT (*SPDA)(int); + int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, PSTR args, int state) { int argc=0; wchar_t** argw=CommandLineToArgvW(GetCommandLineW(),&argc); @@ -29,5 +31,21 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prevInst, PSTR args, int state) { argv[i]=new char[str.size()+1]; strcpy(argv[i],str.c_str()); } + + // set DPI awareness + HMODULE shcore=LoadLibraryW(L"shcore.dll"); + if (shcore!=NULL) { + SPDA ta_SetProcessDpiAwareness=(SPDA)GetProcAddress(shcore,"SetProcessDpiAwareness"); + if (ta_SetProcessDpiAwareness!=NULL) { + HRESULT result=ta_SetProcessDpiAwareness(2); + if (result!=S_OK) { + // ??? + } + } + if (!FreeLibrary(shcore)) { + // ??? + } + } + return main(argc,argv); } From eab12892f510dd8a92c90126336e8b698148fb81 Mon Sep 17 00:00:00 2001 From: cam900 Date: Fri, 21 Oct 2022 17:45:15 +0900 Subject: [PATCH 54/57] Sync vgsound_emu with master --- extern/vgsound_emu-modified/CHANGELOG.md | 7 + extern/vgsound_emu-modified/CMakeLists.txt | 2 +- .../vgsound_emu/src/core/core.hpp | 34 +++ .../vgsound_emu/src/core/util.hpp | 245 ++---------------- .../vgsound_emu/src/core/util/clock_pulse.hpp | 167 ++++++++++++ .../vgsound_emu/src/core/util/mem_intf.hpp | 44 ++++ .../vgsound_emu/src/core/vox/vox.hpp | 10 +- .../vgsound_emu/src/es550x/es550x.hpp | 15 +- .../vgsound_emu/src/k005289/k005289.hpp | 3 +- .../vgsound_emu/src/k007232/k007232.hpp | 4 +- .../vgsound_emu/src/k053260/k053260.hpp | 6 +- .../vgsound_emu/src/msm6295/msm6295.hpp | 24 +- .../vgsound_emu/src/n163/n163.hpp | 4 +- .../vgsound_emu/src/scc/scc.hpp | 5 +- .../vgsound_emu/src/template/template.hpp | 5 +- .../vgsound_emu/src/vrcvi/vrcvi.cpp | 8 +- .../vgsound_emu/src/vrcvi/vrcvi.hpp | 4 +- .../vgsound_emu/src/x1_010/x1_010.hpp | 5 +- 18 files changed, 339 insertions(+), 253 deletions(-) create mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp create mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp create mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp diff --git a/extern/vgsound_emu-modified/CHANGELOG.md b/extern/vgsound_emu-modified/CHANGELOG.md index 305e83377..46957e509 100644 --- a/extern/vgsound_emu-modified/CHANGELOG.md +++ b/extern/vgsound_emu-modified/CHANGELOG.md @@ -2,6 +2,13 @@ ## Important changes +### V 2.1.2 (2022-10-21) + +Split utilities and core framework header +Use static constexprs for global constants +Fix initialization +Fix CMake + ### V 2.1.1 (2022-10-20) Add C++11 detection for CMake diff --git a/extern/vgsound_emu-modified/CMakeLists.txt b/extern/vgsound_emu-modified/CMakeLists.txt index f1ba138e0..0aea2e92a 100644 --- a/extern/vgsound_emu-modified/CMakeLists.txt +++ b/extern/vgsound_emu-modified/CMakeLists.txt @@ -97,8 +97,8 @@ set(EMU_SOURCE "") # Core functions list(APPEND CORE_SOURCE vgsound_emu/src/core/core.hpp + vgsound_emu/src/core/util.hpp vgsound_emu/src/core/util/clock_pulse.hpp - vgsound_emu/src/core/util/fifo.hpp vgsound_emu/src/core/util/mem_intf.hpp ) diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp new file mode 100644 index 000000000..ac0652d0a --- /dev/null +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp @@ -0,0 +1,34 @@ +/* + License: Zlib + see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details + + Copyright holder(s): cam900 + Core framework for vgsound_emu +*/ + +#ifndef _VGSOUND_EMU_SRC_CORE_CORE_HPP +#define _VGSOUND_EMU_SRC_CORE_CORE_HPP + +#pragma once + +#include "util.hpp" + +namespace vgsound_emu +{ + class vgsound_emu_core + { + public: + // constructors + vgsound_emu_core(std::string tag) + : m_tag(tag) + { + } + + // getters + std::string tag() { return m_tag; } + + private: + std::string m_tag = ""; // core tags + }; +}; // namespace vgsound_emu +#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp index a6a9d6a29..5df967f66 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp @@ -32,232 +32,39 @@ namespace vgsound_emu typedef float f32; typedef double f64; - class vgsound_emu_core - { - public: - // constructors - vgsound_emu_core(std::string tag) - : m_tag(tag) - { - } - - // getters - std::string tag() { return m_tag; } - - protected: - const f64 PI = 3.1415926535897932384626433832795; - - // std::clamp is only for C++17 or later; I use my own code - template - T clamp(T in, T min, T max) - { -#if defined(_HAS_CXX17) && _HAS_CXX17 - // just use std::clamp if C++17 or above - return std::clamp(in, min, max); -#else - // otherwise, use my own implementation of std::clamp - return std::min(std::max(in, min), max); -#endif - } - - // get bitfield, bitfield(input, position, len) - template - T bitfield(T in, u8 pos, u8 len = 1) - { - return (in >> pos) & (len ? (T(1 << len) - 1) : 1); - } - - // get sign extended value, sign_ext(input, len) - template - T sign_ext(T in, u8 len) - { - len = std::max(0, (8 * sizeof(T)) - len); - return T(T(in) << len) >> len; - } - - // convert attenuation decibel value to gain - inline f32 dB_to_gain(f32 attenuation) { return std::pow(10.0f, attenuation / 20.0f); } - - private: - std::string m_tag = ""; // core tags - }; - - class vgsound_emu_mem_intf : public vgsound_emu_core - { - public: - // constructor - vgsound_emu_mem_intf() - : vgsound_emu_core("mem_intf") - { - } - - virtual u8 read_byte(u32 address) { return 0; } - - virtual u16 read_word(u32 address) { return 0; } - - virtual u32 read_dword(u32 address) { return 0; } - - virtual u64 read_qword(u32 address) { return 0; } - - virtual void write_byte(u32 address, u8 data) {} - - virtual void write_word(u32 address, u16 data) {} - - virtual void write_dword(u32 address, u32 data) {} - - virtual void write_qword(u32 address, u64 data) {} - }; + static constexpr f64 PI = 3.1415926535897932384626433832795; + // std::clamp is only for C++17 or later; I use my own code template - class clock_pulse_t : public vgsound_emu_core + static inline T clamp(T in, T min, T max) { - private: - const T m_init_width = 1; +#if defined(_HAS_CXX17) && _HAS_CXX17 + // just use std::clamp if C++17 or above + return std::clamp(in, min, max); +#else + // otherwise, use my own implementation of std::clamp + return std::min(std::max(in, min), max); +#endif + } - class edge_t : public vgsound_emu_core - { - private: - const u8 m_init_edge = 1; + // get bitfield, bitfield(input, position, len) + template + static inline T bitfield(T in, u8 pos, u8 len = 1) + { + return (in >> pos) & (len ? (T(1 << len) - 1) : 1); + } - public: - edge_t(u8 init_edge = 0) - : vgsound_emu_core("clock_pulse_edge") - , m_init_edge(init_edge) - , m_current(init_edge ^ 1) - , m_previous(init_edge) - , m_rising(0) - , m_falling(0) - , m_changed(0) - { - set(init_edge); - } + // get sign extended value, sign_ext(input, len) + template + static inline T sign_ext(T in, u8 len) + { + len = std::max(0, (8 * sizeof(T)) - len); + return T(T(in) << len) >> len; + } - // internal states - void reset() - { - m_previous = m_init_edge; - m_current = m_init_edge ^ 1; - set(m_init_edge); - } + // convert attenuation decibel value to gain + static inline f32 dB_to_gain(f32 attenuation) { return std::pow(10.0f, attenuation / 20.0f); } - void tick(bool toggle) - { - u8 current = m_current; - if (toggle) - { - current ^= 1; - } - set(current); - } - - void set(u8 edge) - { - edge &= 1; - m_rising = m_falling = m_changed = 0; - if (m_current != edge) - { - m_changed = 1; - if (m_current && (!edge)) - { - m_falling = 1; - } - else if ((!m_current) && edge) - { - m_rising = 1; - } - m_current = edge; - } - m_previous = m_current; - } - - // getters - inline bool current() { return m_current; } - - inline bool rising() { return m_rising; } - - inline bool falling() { return m_falling; } - - inline bool changed() { return m_changed; } - - private: - u8 m_current : 1; // current edge - u8 m_previous : 1; // previous edge - u8 m_rising : 1; // rising edge - u8 m_falling : 1; // falling edge - u8 m_changed : 1; // changed flag - }; - - public: - clock_pulse_t(T init_width, u8 init_edge = 0) - : vgsound_emu_core("clock_pulse") - , m_init_width(init_width) - , m_edge(edge_t(init_edge & 1)) - , m_width(init_width) - , m_width_latch(init_width) - , m_counter(init_width) - , m_cycle(0) - { - } - - void reset(T init) - { - m_edge.reset(); - m_width = m_width_latch = m_counter = init; - m_cycle = 0; - } - - inline void reset() { reset(m_init_width); } - - bool tick(T width = 0) - { - bool carry = ((--m_counter) <= 0); - if (carry) - { - if (!width) - { - m_width = m_width_latch; - } - else - { - m_width = width; // reset width - } - m_counter = m_width; - m_cycle = 0; - } - else - { - m_cycle++; - } - - m_edge.tick(carry); - return carry; - } - - inline void set_width(T width) { m_width = width; } - - inline void set_width_latch(T width) { m_width_latch = width; } - - // Accessors - inline bool current_edge() { return m_edge.current(); } - - inline bool rising_edge() { return m_edge.rising(); } - - inline bool falling_edge() { return m_edge.falling(); } - - // getters - edge_t &edge() { return m_edge; } - - inline T cycle() { return m_cycle; } - - private: - edge_t m_edge; - T m_width = 1; // clock pulse width - T m_width_latch = 1; // clock pulse width latch - T m_counter = 1; // clock counter - T m_cycle = 0; // clock cycle - }; }; // namespace vgsound_emu -using namespace vgsound_emu; - #endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp new file mode 100644 index 000000000..de6438566 --- /dev/null +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp @@ -0,0 +1,167 @@ +/* + License: Zlib + see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details + + Copyright holder(s): cam900 + Common clock pulse emulation for vgsound_emu +*/ + +#ifndef _VGSOUND_EMU_SRC_CORE_UTIL_CLOCK_PULSE_HPP +#define _VGSOUND_EMU_SRC_CORE_UTIL_CLOCK_PULSE_HPP + +#pragma once + +#include "../core.hpp" + +namespace vgsound_emu +{ + template + class clock_pulse_t : public vgsound_emu_core + { + private: + const T m_init_width = 1; + + class edge_t : public vgsound_emu_core + { + private: + const u8 m_init_edge = 1; + + public: + edge_t(u8 init_edge = 0) + : vgsound_emu_core("clock_pulse_edge") + , m_init_edge(init_edge) + , m_current(init_edge ^ 1) + , m_previous(init_edge) + , m_rising(0) + , m_falling(0) + , m_changed(0) + { + set(init_edge); + } + + // internal states + void reset() + { + m_previous = m_init_edge; + m_current = m_init_edge ^ 1; + set(m_init_edge); + } + + void tick(bool toggle) + { + u8 current = m_current; + if (toggle) + { + current ^= 1; + } + set(current); + } + + void set(u8 edge) + { + edge &= 1; + m_rising = m_falling = m_changed = 0; + if (m_current != edge) + { + m_changed = 1; + if (m_current && (!edge)) + { + m_falling = 1; + } + else if ((!m_current) && edge) + { + m_rising = 1; + } + m_current = edge; + } + m_previous = m_current; + } + + // getters + inline bool current() { return m_current; } + + inline bool rising() { return m_rising; } + + inline bool falling() { return m_falling; } + + inline bool changed() { return m_changed; } + + private: + u8 m_current : 1; // current edge + u8 m_previous : 1; // previous edge + u8 m_rising : 1; // rising edge + u8 m_falling : 1; // falling edge + u8 m_changed : 1; // changed flag + }; + + public: + clock_pulse_t(T init_width, u8 init_edge = 0) + : vgsound_emu_core("clock_pulse") + , m_init_width(init_width) + , m_edge(edge_t(init_edge & 1)) + , m_width(init_width) + , m_width_latch(init_width) + , m_counter(init_width) + , m_cycle(0) + { + } + + void reset(T init) + { + m_edge.reset(); + m_width = m_width_latch = m_counter = init; + m_cycle = 0; + } + + inline void reset() { reset(m_init_width); } + + bool tick(T width = 0) + { + bool carry = ((--m_counter) <= 0); + if (carry) + { + if (!width) + { + m_width = m_width_latch; + } + else + { + m_width = width; // reset width + } + m_counter = m_width; + m_cycle = 0; + } + else + { + m_cycle++; + } + + m_edge.tick(carry); + return carry; + } + + inline void set_width(T width) { m_width = width; } + + inline void set_width_latch(T width) { m_width_latch = width; } + + // Accessors + inline bool current_edge() { return m_edge.current(); } + + inline bool rising_edge() { return m_edge.rising(); } + + inline bool falling_edge() { return m_edge.falling(); } + + // getters + edge_t &edge() { return m_edge; } + + inline T cycle() { return m_cycle; } + + private: + edge_t m_edge; + T m_width = 1; // clock pulse width + T m_width_latch = 1; // clock pulse width latch + T m_counter = 1; // clock counter + T m_cycle = 0; // clock cycle + }; +}; // namespace vgsound_emu +#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp new file mode 100644 index 000000000..8ee051773 --- /dev/null +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp @@ -0,0 +1,44 @@ +/* + License: Zlib + see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details + + Copyright holder(s): cam900 + Common memory interface for vgsound_emu +*/ + +#ifndef _VGSOUND_EMU_SRC_CORE_UTIL_MEM_INTF_HPP +#define _VGSOUND_EMU_SRC_CORE_UTIL_MEM_INTF_HPP + +#pragma once + +#include "../core.hpp" + +namespace vgsound_emu +{ + class vgsound_emu_mem_intf : public vgsound_emu_core + { + public: + // constructor + vgsound_emu_mem_intf() + : vgsound_emu_core("mem_intf") + { + } + + virtual u8 read_byte(u32 address) { return 0; } + + virtual u16 read_word(u32 address) { return 0; } + + virtual u32 read_dword(u32 address) { return 0; } + + virtual u64 read_qword(u32 address) { return 0; } + + virtual void write_byte(u32 address, u8 data) {} + + virtual void write_word(u32 address, u16 data) {} + + virtual void write_dword(u32 address, u32 data) {} + + virtual void write_qword(u32 address, u64 data) {} + }; +}; // namespace vgsound_emu +#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp index 231f9b638..2f42e3945 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp @@ -3,7 +3,7 @@ see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details Copyright holder(s): cam900 - Dialogic ADPCM core + OKI/Dialogic ADPCM core */ #ifndef _VGSOUND_EMU_SRC_CORE_VOX_VOX_HPP @@ -11,7 +11,9 @@ #pragma once -#include "../util.hpp" +#include "../core.hpp" + +using namespace vgsound_emu; class vox_core : public vgsound_emu_core { @@ -93,8 +95,8 @@ class vox_core : public vgsound_emu_core bool m_loop_saved = false; }; - const s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; - const s32 m_step_table[49] = { + static constexpr s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; + static constexpr s32 m_step_table[49] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552}; diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp index 4457c2440..d99fdfbf4 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp @@ -11,7 +11,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/clock_pulse.hpp" + +using namespace vgsound_emu; // ES5504/ES5505/ES5506 interface class es550x_intf : public vgsound_emu_core @@ -168,11 +171,11 @@ class es550x_shared_core : public vgsound_emu_core } // configurations - const u8 m_integer; - const u8 m_fraction; - const u8 m_total_bits; - const u32 m_accum_mask; - const bool m_transwave; + const u8 m_integer = 21; + const u8 m_fraction = 11; + const u8 m_total_bits = 32; + const u32 m_accum_mask = 0xffffffff; + const bool m_transwave = true; // internal states void reset(); diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp index 6fae1f2cb..2c2b0715a 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp @@ -11,7 +11,8 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +using namespace vgsound_emu; class k005289_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp index d500f091a..ef3af56dd 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class k007232_intf : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp index bca78a1f4..a84dc16a8 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class k053260_intf : public vgsound_emu_core { @@ -31,7 +33,7 @@ class k053260_core : public vgsound_emu_core friend class k053260_intf; // k053260 specific interface private: - const int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction + static constexpr int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction class voice_t : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp index 04326ae6d..bb2e6a1cc 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp @@ -11,24 +11,28 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" #include "../core/vox/vox.hpp" +using namespace vgsound_emu; + class msm6295_core : public vox_core { friend class vgsound_emu_mem_intf; // common memory interface private: // Internal volume table, 9 step - const s32 m_volume_table[9] = {32 /* 0.0dB */, - 22 /* -3.2dB */, - 16 /* -6.0dB */, - 11 /* -9.2dB */, - 8 /* -12.0dB */, - 6 /* -14.5dB */, - 4 /* -18.0dB */, - 3 /* -20.5dB */, - 2 /* -24.0dB */}; // scale out to 5 bit for optimization + static constexpr s32 m_volume_table[9] = { + 32 /* 0.0dB */, + 22 /* -3.2dB */, + 16 /* -6.0dB */, + 11 /* -9.2dB */, + 8 /* -12.0dB */, + 6 /* -14.5dB */, + 4 /* -18.0dB */, + 3 /* -20.5dB */, + 2 /* -24.0dB */}; // scale out to 5 bit for optimization // msm6295 voice classes class voice_t : vox_decoder_t diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp index 1c04d1f36..bbf2720ac 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class n163_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp index 8824d2535..12322d84f 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp @@ -12,7 +12,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" + +using namespace vgsound_emu; // shared for SCCs class scc_core : public vgsound_emu_core diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp index ca8f91b53..ffc6f9321 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp @@ -11,7 +11,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" + +using namespace vgsound_emu; class template_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp index dc59120f3..8ff62fead 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp @@ -61,10 +61,10 @@ bool vrcvi_core::alu_t::tick() } // carry handling - bool carry = bitfield(m_host.m_control.shift(), 1) - ? (bitfield(temp, 8, 4) == 0) - : (bitfield(m_host.m_control.shift(), 0) ? (bitfield(temp, 4, 8) == 0) - : (bitfield(temp, 0, 12) == 0)); + const bool carry = bitfield(m_host.m_control.shift(), 1) + ? (bitfield(temp, 8, 4) == 0) + : (bitfield(m_host.m_control.shift(), 0) ? (bitfield(temp, 4, 8) == 0) + : (bitfield(temp, 0, 12) == 0)); if (carry) { m_counter = m_divider.divider(); diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp index f163114c0..d6694aaef 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class vrcvi_intf : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp index 34a4ab99a..37a1895bd 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp @@ -11,7 +11,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" + +using namespace vgsound_emu; class x1_010_core : public vgsound_emu_core { From f832ce5cca28ca082566117924ee643d5647904c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Fri, 21 Oct 2022 17:16:40 -0500 Subject: [PATCH 55/57] Temporarily revert "Sync vgsound_emu with master" issue #720 This reverts commit eab12892f510dd8a92c90126336e8b698148fb81. to cam900: feel free to revert this revert commit after fixing vgsound_emu. --- extern/vgsound_emu-modified/CHANGELOG.md | 7 - extern/vgsound_emu-modified/CMakeLists.txt | 2 +- .../vgsound_emu/src/core/core.hpp | 34 --- .../vgsound_emu/src/core/util.hpp | 237 ++++++++++++++++-- .../vgsound_emu/src/core/util/clock_pulse.hpp | 167 ------------ .../vgsound_emu/src/core/util/mem_intf.hpp | 44 ---- .../vgsound_emu/src/core/vox/vox.hpp | 10 +- .../vgsound_emu/src/es550x/es550x.hpp | 15 +- .../vgsound_emu/src/k005289/k005289.hpp | 3 +- .../vgsound_emu/src/k007232/k007232.hpp | 4 +- .../vgsound_emu/src/k053260/k053260.hpp | 6 +- .../vgsound_emu/src/msm6295/msm6295.hpp | 24 +- .../vgsound_emu/src/n163/n163.hpp | 4 +- .../vgsound_emu/src/scc/scc.hpp | 5 +- .../vgsound_emu/src/template/template.hpp | 5 +- .../vgsound_emu/src/vrcvi/vrcvi.cpp | 8 +- .../vgsound_emu/src/vrcvi/vrcvi.hpp | 4 +- .../vgsound_emu/src/x1_010/x1_010.hpp | 5 +- 18 files changed, 249 insertions(+), 335 deletions(-) delete mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp delete mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp delete mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp diff --git a/extern/vgsound_emu-modified/CHANGELOG.md b/extern/vgsound_emu-modified/CHANGELOG.md index 46957e509..305e83377 100644 --- a/extern/vgsound_emu-modified/CHANGELOG.md +++ b/extern/vgsound_emu-modified/CHANGELOG.md @@ -2,13 +2,6 @@ ## Important changes -### V 2.1.2 (2022-10-21) - -Split utilities and core framework header -Use static constexprs for global constants -Fix initialization -Fix CMake - ### V 2.1.1 (2022-10-20) Add C++11 detection for CMake diff --git a/extern/vgsound_emu-modified/CMakeLists.txt b/extern/vgsound_emu-modified/CMakeLists.txt index 0aea2e92a..f1ba138e0 100644 --- a/extern/vgsound_emu-modified/CMakeLists.txt +++ b/extern/vgsound_emu-modified/CMakeLists.txt @@ -97,8 +97,8 @@ set(EMU_SOURCE "") # Core functions list(APPEND CORE_SOURCE vgsound_emu/src/core/core.hpp - vgsound_emu/src/core/util.hpp vgsound_emu/src/core/util/clock_pulse.hpp + vgsound_emu/src/core/util/fifo.hpp vgsound_emu/src/core/util/mem_intf.hpp ) diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp deleted file mode 100644 index ac0652d0a..000000000 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - License: Zlib - see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details - - Copyright holder(s): cam900 - Core framework for vgsound_emu -*/ - -#ifndef _VGSOUND_EMU_SRC_CORE_CORE_HPP -#define _VGSOUND_EMU_SRC_CORE_CORE_HPP - -#pragma once - -#include "util.hpp" - -namespace vgsound_emu -{ - class vgsound_emu_core - { - public: - // constructors - vgsound_emu_core(std::string tag) - : m_tag(tag) - { - } - - // getters - std::string tag() { return m_tag; } - - private: - std::string m_tag = ""; // core tags - }; -}; // namespace vgsound_emu -#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp index 5df967f66..a6a9d6a29 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp @@ -32,39 +32,232 @@ namespace vgsound_emu typedef float f32; typedef double f64; - static constexpr f64 PI = 3.1415926535897932384626433832795; - - // std::clamp is only for C++17 or later; I use my own code - template - static inline T clamp(T in, T min, T max) + class vgsound_emu_core { + public: + // constructors + vgsound_emu_core(std::string tag) + : m_tag(tag) + { + } + + // getters + std::string tag() { return m_tag; } + + protected: + const f64 PI = 3.1415926535897932384626433832795; + + // std::clamp is only for C++17 or later; I use my own code + template + T clamp(T in, T min, T max) + { #if defined(_HAS_CXX17) && _HAS_CXX17 - // just use std::clamp if C++17 or above - return std::clamp(in, min, max); + // just use std::clamp if C++17 or above + return std::clamp(in, min, max); #else - // otherwise, use my own implementation of std::clamp - return std::min(std::max(in, min), max); + // otherwise, use my own implementation of std::clamp + return std::min(std::max(in, min), max); #endif - } + } - // get bitfield, bitfield(input, position, len) - template - static inline T bitfield(T in, u8 pos, u8 len = 1) + // get bitfield, bitfield(input, position, len) + template + T bitfield(T in, u8 pos, u8 len = 1) + { + return (in >> pos) & (len ? (T(1 << len) - 1) : 1); + } + + // get sign extended value, sign_ext(input, len) + template + T sign_ext(T in, u8 len) + { + len = std::max(0, (8 * sizeof(T)) - len); + return T(T(in) << len) >> len; + } + + // convert attenuation decibel value to gain + inline f32 dB_to_gain(f32 attenuation) { return std::pow(10.0f, attenuation / 20.0f); } + + private: + std::string m_tag = ""; // core tags + }; + + class vgsound_emu_mem_intf : public vgsound_emu_core { - return (in >> pos) & (len ? (T(1 << len) - 1) : 1); - } + public: + // constructor + vgsound_emu_mem_intf() + : vgsound_emu_core("mem_intf") + { + } + + virtual u8 read_byte(u32 address) { return 0; } + + virtual u16 read_word(u32 address) { return 0; } + + virtual u32 read_dword(u32 address) { return 0; } + + virtual u64 read_qword(u32 address) { return 0; } + + virtual void write_byte(u32 address, u8 data) {} + + virtual void write_word(u32 address, u16 data) {} + + virtual void write_dword(u32 address, u32 data) {} + + virtual void write_qword(u32 address, u64 data) {} + }; - // get sign extended value, sign_ext(input, len) template - static inline T sign_ext(T in, u8 len) + class clock_pulse_t : public vgsound_emu_core { - len = std::max(0, (8 * sizeof(T)) - len); - return T(T(in) << len) >> len; - } + private: + const T m_init_width = 1; - // convert attenuation decibel value to gain - static inline f32 dB_to_gain(f32 attenuation) { return std::pow(10.0f, attenuation / 20.0f); } + class edge_t : public vgsound_emu_core + { + private: + const u8 m_init_edge = 1; + public: + edge_t(u8 init_edge = 0) + : vgsound_emu_core("clock_pulse_edge") + , m_init_edge(init_edge) + , m_current(init_edge ^ 1) + , m_previous(init_edge) + , m_rising(0) + , m_falling(0) + , m_changed(0) + { + set(init_edge); + } + + // internal states + void reset() + { + m_previous = m_init_edge; + m_current = m_init_edge ^ 1; + set(m_init_edge); + } + + void tick(bool toggle) + { + u8 current = m_current; + if (toggle) + { + current ^= 1; + } + set(current); + } + + void set(u8 edge) + { + edge &= 1; + m_rising = m_falling = m_changed = 0; + if (m_current != edge) + { + m_changed = 1; + if (m_current && (!edge)) + { + m_falling = 1; + } + else if ((!m_current) && edge) + { + m_rising = 1; + } + m_current = edge; + } + m_previous = m_current; + } + + // getters + inline bool current() { return m_current; } + + inline bool rising() { return m_rising; } + + inline bool falling() { return m_falling; } + + inline bool changed() { return m_changed; } + + private: + u8 m_current : 1; // current edge + u8 m_previous : 1; // previous edge + u8 m_rising : 1; // rising edge + u8 m_falling : 1; // falling edge + u8 m_changed : 1; // changed flag + }; + + public: + clock_pulse_t(T init_width, u8 init_edge = 0) + : vgsound_emu_core("clock_pulse") + , m_init_width(init_width) + , m_edge(edge_t(init_edge & 1)) + , m_width(init_width) + , m_width_latch(init_width) + , m_counter(init_width) + , m_cycle(0) + { + } + + void reset(T init) + { + m_edge.reset(); + m_width = m_width_latch = m_counter = init; + m_cycle = 0; + } + + inline void reset() { reset(m_init_width); } + + bool tick(T width = 0) + { + bool carry = ((--m_counter) <= 0); + if (carry) + { + if (!width) + { + m_width = m_width_latch; + } + else + { + m_width = width; // reset width + } + m_counter = m_width; + m_cycle = 0; + } + else + { + m_cycle++; + } + + m_edge.tick(carry); + return carry; + } + + inline void set_width(T width) { m_width = width; } + + inline void set_width_latch(T width) { m_width_latch = width; } + + // Accessors + inline bool current_edge() { return m_edge.current(); } + + inline bool rising_edge() { return m_edge.rising(); } + + inline bool falling_edge() { return m_edge.falling(); } + + // getters + edge_t &edge() { return m_edge; } + + inline T cycle() { return m_cycle; } + + private: + edge_t m_edge; + T m_width = 1; // clock pulse width + T m_width_latch = 1; // clock pulse width latch + T m_counter = 1; // clock counter + T m_cycle = 0; // clock cycle + }; }; // namespace vgsound_emu +using namespace vgsound_emu; + #endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp deleted file mode 100644 index de6438566..000000000 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - License: Zlib - see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details - - Copyright holder(s): cam900 - Common clock pulse emulation for vgsound_emu -*/ - -#ifndef _VGSOUND_EMU_SRC_CORE_UTIL_CLOCK_PULSE_HPP -#define _VGSOUND_EMU_SRC_CORE_UTIL_CLOCK_PULSE_HPP - -#pragma once - -#include "../core.hpp" - -namespace vgsound_emu -{ - template - class clock_pulse_t : public vgsound_emu_core - { - private: - const T m_init_width = 1; - - class edge_t : public vgsound_emu_core - { - private: - const u8 m_init_edge = 1; - - public: - edge_t(u8 init_edge = 0) - : vgsound_emu_core("clock_pulse_edge") - , m_init_edge(init_edge) - , m_current(init_edge ^ 1) - , m_previous(init_edge) - , m_rising(0) - , m_falling(0) - , m_changed(0) - { - set(init_edge); - } - - // internal states - void reset() - { - m_previous = m_init_edge; - m_current = m_init_edge ^ 1; - set(m_init_edge); - } - - void tick(bool toggle) - { - u8 current = m_current; - if (toggle) - { - current ^= 1; - } - set(current); - } - - void set(u8 edge) - { - edge &= 1; - m_rising = m_falling = m_changed = 0; - if (m_current != edge) - { - m_changed = 1; - if (m_current && (!edge)) - { - m_falling = 1; - } - else if ((!m_current) && edge) - { - m_rising = 1; - } - m_current = edge; - } - m_previous = m_current; - } - - // getters - inline bool current() { return m_current; } - - inline bool rising() { return m_rising; } - - inline bool falling() { return m_falling; } - - inline bool changed() { return m_changed; } - - private: - u8 m_current : 1; // current edge - u8 m_previous : 1; // previous edge - u8 m_rising : 1; // rising edge - u8 m_falling : 1; // falling edge - u8 m_changed : 1; // changed flag - }; - - public: - clock_pulse_t(T init_width, u8 init_edge = 0) - : vgsound_emu_core("clock_pulse") - , m_init_width(init_width) - , m_edge(edge_t(init_edge & 1)) - , m_width(init_width) - , m_width_latch(init_width) - , m_counter(init_width) - , m_cycle(0) - { - } - - void reset(T init) - { - m_edge.reset(); - m_width = m_width_latch = m_counter = init; - m_cycle = 0; - } - - inline void reset() { reset(m_init_width); } - - bool tick(T width = 0) - { - bool carry = ((--m_counter) <= 0); - if (carry) - { - if (!width) - { - m_width = m_width_latch; - } - else - { - m_width = width; // reset width - } - m_counter = m_width; - m_cycle = 0; - } - else - { - m_cycle++; - } - - m_edge.tick(carry); - return carry; - } - - inline void set_width(T width) { m_width = width; } - - inline void set_width_latch(T width) { m_width_latch = width; } - - // Accessors - inline bool current_edge() { return m_edge.current(); } - - inline bool rising_edge() { return m_edge.rising(); } - - inline bool falling_edge() { return m_edge.falling(); } - - // getters - edge_t &edge() { return m_edge; } - - inline T cycle() { return m_cycle; } - - private: - edge_t m_edge; - T m_width = 1; // clock pulse width - T m_width_latch = 1; // clock pulse width latch - T m_counter = 1; // clock counter - T m_cycle = 0; // clock cycle - }; -}; // namespace vgsound_emu -#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp deleted file mode 100644 index 8ee051773..000000000 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - License: Zlib - see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details - - Copyright holder(s): cam900 - Common memory interface for vgsound_emu -*/ - -#ifndef _VGSOUND_EMU_SRC_CORE_UTIL_MEM_INTF_HPP -#define _VGSOUND_EMU_SRC_CORE_UTIL_MEM_INTF_HPP - -#pragma once - -#include "../core.hpp" - -namespace vgsound_emu -{ - class vgsound_emu_mem_intf : public vgsound_emu_core - { - public: - // constructor - vgsound_emu_mem_intf() - : vgsound_emu_core("mem_intf") - { - } - - virtual u8 read_byte(u32 address) { return 0; } - - virtual u16 read_word(u32 address) { return 0; } - - virtual u32 read_dword(u32 address) { return 0; } - - virtual u64 read_qword(u32 address) { return 0; } - - virtual void write_byte(u32 address, u8 data) {} - - virtual void write_word(u32 address, u16 data) {} - - virtual void write_dword(u32 address, u32 data) {} - - virtual void write_qword(u32 address, u64 data) {} - }; -}; // namespace vgsound_emu -#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp index 2f42e3945..231f9b638 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp @@ -3,7 +3,7 @@ see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details Copyright holder(s): cam900 - OKI/Dialogic ADPCM core + Dialogic ADPCM core */ #ifndef _VGSOUND_EMU_SRC_CORE_VOX_VOX_HPP @@ -11,9 +11,7 @@ #pragma once -#include "../core.hpp" - -using namespace vgsound_emu; +#include "../util.hpp" class vox_core : public vgsound_emu_core { @@ -95,8 +93,8 @@ class vox_core : public vgsound_emu_core bool m_loop_saved = false; }; - static constexpr s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; - static constexpr s32 m_step_table[49] = { + const s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; + const s32 m_step_table[49] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552}; diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp index d99fdfbf4..4457c2440 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp @@ -11,10 +11,7 @@ #pragma once -#include "../core/core.hpp" -#include "../core/util/clock_pulse.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" // ES5504/ES5505/ES5506 interface class es550x_intf : public vgsound_emu_core @@ -171,11 +168,11 @@ class es550x_shared_core : public vgsound_emu_core } // configurations - const u8 m_integer = 21; - const u8 m_fraction = 11; - const u8 m_total_bits = 32; - const u32 m_accum_mask = 0xffffffff; - const bool m_transwave = true; + const u8 m_integer; + const u8 m_fraction; + const u8 m_total_bits; + const u32 m_accum_mask; + const bool m_transwave; // internal states void reset(); diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp index 2c2b0715a..6fae1f2cb 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp @@ -11,8 +11,7 @@ #pragma once -#include "../core/core.hpp" -using namespace vgsound_emu; +#include "../core/util.hpp" class k005289_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp index ef3af56dd..d500f091a 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp @@ -11,9 +11,7 @@ #pragma once -#include "../core/core.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" class k007232_intf : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp index a84dc16a8..bca78a1f4 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp @@ -11,9 +11,7 @@ #pragma once -#include "../core/core.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" class k053260_intf : public vgsound_emu_core { @@ -33,7 +31,7 @@ class k053260_core : public vgsound_emu_core friend class k053260_intf; // k053260 specific interface private: - static constexpr int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction + const int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction class voice_t : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp index bb2e6a1cc..04326ae6d 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp @@ -11,28 +11,24 @@ #pragma once -#include "../core/core.hpp" -#include "../core/util/mem_intf.hpp" +#include "../core/util.hpp" #include "../core/vox/vox.hpp" -using namespace vgsound_emu; - class msm6295_core : public vox_core { friend class vgsound_emu_mem_intf; // common memory interface private: // Internal volume table, 9 step - static constexpr s32 m_volume_table[9] = { - 32 /* 0.0dB */, - 22 /* -3.2dB */, - 16 /* -6.0dB */, - 11 /* -9.2dB */, - 8 /* -12.0dB */, - 6 /* -14.5dB */, - 4 /* -18.0dB */, - 3 /* -20.5dB */, - 2 /* -24.0dB */}; // scale out to 5 bit for optimization + const s32 m_volume_table[9] = {32 /* 0.0dB */, + 22 /* -3.2dB */, + 16 /* -6.0dB */, + 11 /* -9.2dB */, + 8 /* -12.0dB */, + 6 /* -14.5dB */, + 4 /* -18.0dB */, + 3 /* -20.5dB */, + 2 /* -24.0dB */}; // scale out to 5 bit for optimization // msm6295 voice classes class voice_t : vox_decoder_t diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp index bbf2720ac..1c04d1f36 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp @@ -11,9 +11,7 @@ #pragma once -#include "../core/core.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" class n163_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp index 12322d84f..8824d2535 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp @@ -12,10 +12,7 @@ #pragma once -#include "../core/core.hpp" -#include "../core/util/mem_intf.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" // shared for SCCs class scc_core : public vgsound_emu_core diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp index ffc6f9321..ca8f91b53 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp @@ -11,10 +11,7 @@ #pragma once -#include "../core/core.hpp" -#include "../core/util/mem_intf.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" class template_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp index 8ff62fead..dc59120f3 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp @@ -61,10 +61,10 @@ bool vrcvi_core::alu_t::tick() } // carry handling - const bool carry = bitfield(m_host.m_control.shift(), 1) - ? (bitfield(temp, 8, 4) == 0) - : (bitfield(m_host.m_control.shift(), 0) ? (bitfield(temp, 4, 8) == 0) - : (bitfield(temp, 0, 12) == 0)); + bool carry = bitfield(m_host.m_control.shift(), 1) + ? (bitfield(temp, 8, 4) == 0) + : (bitfield(m_host.m_control.shift(), 0) ? (bitfield(temp, 4, 8) == 0) + : (bitfield(temp, 0, 12) == 0)); if (carry) { m_counter = m_divider.divider(); diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp index d6694aaef..f163114c0 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp @@ -11,9 +11,7 @@ #pragma once -#include "../core/core.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" class vrcvi_intf : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp index 37a1895bd..34a4ab99a 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp @@ -11,10 +11,7 @@ #pragma once -#include "../core/core.hpp" -#include "../core/util/mem_intf.hpp" - -using namespace vgsound_emu; +#include "../core/util.hpp" class x1_010_core : public vgsound_emu_core { From 61aeb0bb5ec4b7e1532ac5e606523eb64e58d920 Mon Sep 17 00:00:00 2001 From: cam900 Date: Sat, 22 Oct 2022 10:10:02 +0900 Subject: [PATCH 56/57] Revert "Temporarily revert "Sync vgsound_emu with master"" This reverts commit f832ce5cca28ca082566117924ee643d5647904c. --- extern/vgsound_emu-modified/CHANGELOG.md | 7 + extern/vgsound_emu-modified/CMakeLists.txt | 2 +- .../vgsound_emu/src/core/core.hpp | 34 +++ .../vgsound_emu/src/core/util.hpp | 245 ++---------------- .../vgsound_emu/src/core/util/clock_pulse.hpp | 167 ++++++++++++ .../vgsound_emu/src/core/util/mem_intf.hpp | 44 ++++ .../vgsound_emu/src/core/vox/vox.hpp | 10 +- .../vgsound_emu/src/es550x/es550x.hpp | 15 +- .../vgsound_emu/src/k005289/k005289.hpp | 3 +- .../vgsound_emu/src/k007232/k007232.hpp | 4 +- .../vgsound_emu/src/k053260/k053260.hpp | 6 +- .../vgsound_emu/src/msm6295/msm6295.hpp | 24 +- .../vgsound_emu/src/n163/n163.hpp | 4 +- .../vgsound_emu/src/scc/scc.hpp | 5 +- .../vgsound_emu/src/template/template.hpp | 5 +- .../vgsound_emu/src/vrcvi/vrcvi.cpp | 8 +- .../vgsound_emu/src/vrcvi/vrcvi.hpp | 4 +- .../vgsound_emu/src/x1_010/x1_010.hpp | 5 +- 18 files changed, 339 insertions(+), 253 deletions(-) create mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp create mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp create mode 100644 extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp diff --git a/extern/vgsound_emu-modified/CHANGELOG.md b/extern/vgsound_emu-modified/CHANGELOG.md index 305e83377..46957e509 100644 --- a/extern/vgsound_emu-modified/CHANGELOG.md +++ b/extern/vgsound_emu-modified/CHANGELOG.md @@ -2,6 +2,13 @@ ## Important changes +### V 2.1.2 (2022-10-21) + +Split utilities and core framework header +Use static constexprs for global constants +Fix initialization +Fix CMake + ### V 2.1.1 (2022-10-20) Add C++11 detection for CMake diff --git a/extern/vgsound_emu-modified/CMakeLists.txt b/extern/vgsound_emu-modified/CMakeLists.txt index f1ba138e0..0aea2e92a 100644 --- a/extern/vgsound_emu-modified/CMakeLists.txt +++ b/extern/vgsound_emu-modified/CMakeLists.txt @@ -97,8 +97,8 @@ set(EMU_SOURCE "") # Core functions list(APPEND CORE_SOURCE vgsound_emu/src/core/core.hpp + vgsound_emu/src/core/util.hpp vgsound_emu/src/core/util/clock_pulse.hpp - vgsound_emu/src/core/util/fifo.hpp vgsound_emu/src/core/util/mem_intf.hpp ) diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp new file mode 100644 index 000000000..ac0652d0a --- /dev/null +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/core.hpp @@ -0,0 +1,34 @@ +/* + License: Zlib + see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details + + Copyright holder(s): cam900 + Core framework for vgsound_emu +*/ + +#ifndef _VGSOUND_EMU_SRC_CORE_CORE_HPP +#define _VGSOUND_EMU_SRC_CORE_CORE_HPP + +#pragma once + +#include "util.hpp" + +namespace vgsound_emu +{ + class vgsound_emu_core + { + public: + // constructors + vgsound_emu_core(std::string tag) + : m_tag(tag) + { + } + + // getters + std::string tag() { return m_tag; } + + private: + std::string m_tag = ""; // core tags + }; +}; // namespace vgsound_emu +#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp index a6a9d6a29..5df967f66 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util.hpp @@ -32,232 +32,39 @@ namespace vgsound_emu typedef float f32; typedef double f64; - class vgsound_emu_core - { - public: - // constructors - vgsound_emu_core(std::string tag) - : m_tag(tag) - { - } - - // getters - std::string tag() { return m_tag; } - - protected: - const f64 PI = 3.1415926535897932384626433832795; - - // std::clamp is only for C++17 or later; I use my own code - template - T clamp(T in, T min, T max) - { -#if defined(_HAS_CXX17) && _HAS_CXX17 - // just use std::clamp if C++17 or above - return std::clamp(in, min, max); -#else - // otherwise, use my own implementation of std::clamp - return std::min(std::max(in, min), max); -#endif - } - - // get bitfield, bitfield(input, position, len) - template - T bitfield(T in, u8 pos, u8 len = 1) - { - return (in >> pos) & (len ? (T(1 << len) - 1) : 1); - } - - // get sign extended value, sign_ext(input, len) - template - T sign_ext(T in, u8 len) - { - len = std::max(0, (8 * sizeof(T)) - len); - return T(T(in) << len) >> len; - } - - // convert attenuation decibel value to gain - inline f32 dB_to_gain(f32 attenuation) { return std::pow(10.0f, attenuation / 20.0f); } - - private: - std::string m_tag = ""; // core tags - }; - - class vgsound_emu_mem_intf : public vgsound_emu_core - { - public: - // constructor - vgsound_emu_mem_intf() - : vgsound_emu_core("mem_intf") - { - } - - virtual u8 read_byte(u32 address) { return 0; } - - virtual u16 read_word(u32 address) { return 0; } - - virtual u32 read_dword(u32 address) { return 0; } - - virtual u64 read_qword(u32 address) { return 0; } - - virtual void write_byte(u32 address, u8 data) {} - - virtual void write_word(u32 address, u16 data) {} - - virtual void write_dword(u32 address, u32 data) {} - - virtual void write_qword(u32 address, u64 data) {} - }; + static constexpr f64 PI = 3.1415926535897932384626433832795; + // std::clamp is only for C++17 or later; I use my own code template - class clock_pulse_t : public vgsound_emu_core + static inline T clamp(T in, T min, T max) { - private: - const T m_init_width = 1; +#if defined(_HAS_CXX17) && _HAS_CXX17 + // just use std::clamp if C++17 or above + return std::clamp(in, min, max); +#else + // otherwise, use my own implementation of std::clamp + return std::min(std::max(in, min), max); +#endif + } - class edge_t : public vgsound_emu_core - { - private: - const u8 m_init_edge = 1; + // get bitfield, bitfield(input, position, len) + template + static inline T bitfield(T in, u8 pos, u8 len = 1) + { + return (in >> pos) & (len ? (T(1 << len) - 1) : 1); + } - public: - edge_t(u8 init_edge = 0) - : vgsound_emu_core("clock_pulse_edge") - , m_init_edge(init_edge) - , m_current(init_edge ^ 1) - , m_previous(init_edge) - , m_rising(0) - , m_falling(0) - , m_changed(0) - { - set(init_edge); - } + // get sign extended value, sign_ext(input, len) + template + static inline T sign_ext(T in, u8 len) + { + len = std::max(0, (8 * sizeof(T)) - len); + return T(T(in) << len) >> len; + } - // internal states - void reset() - { - m_previous = m_init_edge; - m_current = m_init_edge ^ 1; - set(m_init_edge); - } + // convert attenuation decibel value to gain + static inline f32 dB_to_gain(f32 attenuation) { return std::pow(10.0f, attenuation / 20.0f); } - void tick(bool toggle) - { - u8 current = m_current; - if (toggle) - { - current ^= 1; - } - set(current); - } - - void set(u8 edge) - { - edge &= 1; - m_rising = m_falling = m_changed = 0; - if (m_current != edge) - { - m_changed = 1; - if (m_current && (!edge)) - { - m_falling = 1; - } - else if ((!m_current) && edge) - { - m_rising = 1; - } - m_current = edge; - } - m_previous = m_current; - } - - // getters - inline bool current() { return m_current; } - - inline bool rising() { return m_rising; } - - inline bool falling() { return m_falling; } - - inline bool changed() { return m_changed; } - - private: - u8 m_current : 1; // current edge - u8 m_previous : 1; // previous edge - u8 m_rising : 1; // rising edge - u8 m_falling : 1; // falling edge - u8 m_changed : 1; // changed flag - }; - - public: - clock_pulse_t(T init_width, u8 init_edge = 0) - : vgsound_emu_core("clock_pulse") - , m_init_width(init_width) - , m_edge(edge_t(init_edge & 1)) - , m_width(init_width) - , m_width_latch(init_width) - , m_counter(init_width) - , m_cycle(0) - { - } - - void reset(T init) - { - m_edge.reset(); - m_width = m_width_latch = m_counter = init; - m_cycle = 0; - } - - inline void reset() { reset(m_init_width); } - - bool tick(T width = 0) - { - bool carry = ((--m_counter) <= 0); - if (carry) - { - if (!width) - { - m_width = m_width_latch; - } - else - { - m_width = width; // reset width - } - m_counter = m_width; - m_cycle = 0; - } - else - { - m_cycle++; - } - - m_edge.tick(carry); - return carry; - } - - inline void set_width(T width) { m_width = width; } - - inline void set_width_latch(T width) { m_width_latch = width; } - - // Accessors - inline bool current_edge() { return m_edge.current(); } - - inline bool rising_edge() { return m_edge.rising(); } - - inline bool falling_edge() { return m_edge.falling(); } - - // getters - edge_t &edge() { return m_edge; } - - inline T cycle() { return m_cycle; } - - private: - edge_t m_edge; - T m_width = 1; // clock pulse width - T m_width_latch = 1; // clock pulse width latch - T m_counter = 1; // clock counter - T m_cycle = 0; // clock cycle - }; }; // namespace vgsound_emu -using namespace vgsound_emu; - #endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp new file mode 100644 index 000000000..de6438566 --- /dev/null +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/clock_pulse.hpp @@ -0,0 +1,167 @@ +/* + License: Zlib + see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details + + Copyright holder(s): cam900 + Common clock pulse emulation for vgsound_emu +*/ + +#ifndef _VGSOUND_EMU_SRC_CORE_UTIL_CLOCK_PULSE_HPP +#define _VGSOUND_EMU_SRC_CORE_UTIL_CLOCK_PULSE_HPP + +#pragma once + +#include "../core.hpp" + +namespace vgsound_emu +{ + template + class clock_pulse_t : public vgsound_emu_core + { + private: + const T m_init_width = 1; + + class edge_t : public vgsound_emu_core + { + private: + const u8 m_init_edge = 1; + + public: + edge_t(u8 init_edge = 0) + : vgsound_emu_core("clock_pulse_edge") + , m_init_edge(init_edge) + , m_current(init_edge ^ 1) + , m_previous(init_edge) + , m_rising(0) + , m_falling(0) + , m_changed(0) + { + set(init_edge); + } + + // internal states + void reset() + { + m_previous = m_init_edge; + m_current = m_init_edge ^ 1; + set(m_init_edge); + } + + void tick(bool toggle) + { + u8 current = m_current; + if (toggle) + { + current ^= 1; + } + set(current); + } + + void set(u8 edge) + { + edge &= 1; + m_rising = m_falling = m_changed = 0; + if (m_current != edge) + { + m_changed = 1; + if (m_current && (!edge)) + { + m_falling = 1; + } + else if ((!m_current) && edge) + { + m_rising = 1; + } + m_current = edge; + } + m_previous = m_current; + } + + // getters + inline bool current() { return m_current; } + + inline bool rising() { return m_rising; } + + inline bool falling() { return m_falling; } + + inline bool changed() { return m_changed; } + + private: + u8 m_current : 1; // current edge + u8 m_previous : 1; // previous edge + u8 m_rising : 1; // rising edge + u8 m_falling : 1; // falling edge + u8 m_changed : 1; // changed flag + }; + + public: + clock_pulse_t(T init_width, u8 init_edge = 0) + : vgsound_emu_core("clock_pulse") + , m_init_width(init_width) + , m_edge(edge_t(init_edge & 1)) + , m_width(init_width) + , m_width_latch(init_width) + , m_counter(init_width) + , m_cycle(0) + { + } + + void reset(T init) + { + m_edge.reset(); + m_width = m_width_latch = m_counter = init; + m_cycle = 0; + } + + inline void reset() { reset(m_init_width); } + + bool tick(T width = 0) + { + bool carry = ((--m_counter) <= 0); + if (carry) + { + if (!width) + { + m_width = m_width_latch; + } + else + { + m_width = width; // reset width + } + m_counter = m_width; + m_cycle = 0; + } + else + { + m_cycle++; + } + + m_edge.tick(carry); + return carry; + } + + inline void set_width(T width) { m_width = width; } + + inline void set_width_latch(T width) { m_width_latch = width; } + + // Accessors + inline bool current_edge() { return m_edge.current(); } + + inline bool rising_edge() { return m_edge.rising(); } + + inline bool falling_edge() { return m_edge.falling(); } + + // getters + edge_t &edge() { return m_edge; } + + inline T cycle() { return m_cycle; } + + private: + edge_t m_edge; + T m_width = 1; // clock pulse width + T m_width_latch = 1; // clock pulse width latch + T m_counter = 1; // clock counter + T m_cycle = 0; // clock cycle + }; +}; // namespace vgsound_emu +#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp new file mode 100644 index 000000000..8ee051773 --- /dev/null +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/util/mem_intf.hpp @@ -0,0 +1,44 @@ +/* + License: Zlib + see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details + + Copyright holder(s): cam900 + Common memory interface for vgsound_emu +*/ + +#ifndef _VGSOUND_EMU_SRC_CORE_UTIL_MEM_INTF_HPP +#define _VGSOUND_EMU_SRC_CORE_UTIL_MEM_INTF_HPP + +#pragma once + +#include "../core.hpp" + +namespace vgsound_emu +{ + class vgsound_emu_mem_intf : public vgsound_emu_core + { + public: + // constructor + vgsound_emu_mem_intf() + : vgsound_emu_core("mem_intf") + { + } + + virtual u8 read_byte(u32 address) { return 0; } + + virtual u16 read_word(u32 address) { return 0; } + + virtual u32 read_dword(u32 address) { return 0; } + + virtual u64 read_qword(u32 address) { return 0; } + + virtual void write_byte(u32 address, u8 data) {} + + virtual void write_word(u32 address, u16 data) {} + + virtual void write_dword(u32 address, u32 data) {} + + virtual void write_qword(u32 address, u64 data) {} + }; +}; // namespace vgsound_emu +#endif diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp index 231f9b638..2f42e3945 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp @@ -3,7 +3,7 @@ see https://gitlab.com/cam900/vgsound_emu/-/blob/main/LICENSE for more details Copyright holder(s): cam900 - Dialogic ADPCM core + OKI/Dialogic ADPCM core */ #ifndef _VGSOUND_EMU_SRC_CORE_VOX_VOX_HPP @@ -11,7 +11,9 @@ #pragma once -#include "../util.hpp" +#include "../core.hpp" + +using namespace vgsound_emu; class vox_core : public vgsound_emu_core { @@ -93,8 +95,8 @@ class vox_core : public vgsound_emu_core bool m_loop_saved = false; }; - const s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; - const s32 m_step_table[49] = { + static constexpr s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; + static constexpr s32 m_step_table[49] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552}; diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp index 4457c2440..d99fdfbf4 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/es550x/es550x.hpp @@ -11,7 +11,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/clock_pulse.hpp" + +using namespace vgsound_emu; // ES5504/ES5505/ES5506 interface class es550x_intf : public vgsound_emu_core @@ -168,11 +171,11 @@ class es550x_shared_core : public vgsound_emu_core } // configurations - const u8 m_integer; - const u8 m_fraction; - const u8 m_total_bits; - const u32 m_accum_mask; - const bool m_transwave; + const u8 m_integer = 21; + const u8 m_fraction = 11; + const u8 m_total_bits = 32; + const u32 m_accum_mask = 0xffffffff; + const bool m_transwave = true; // internal states void reset(); diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp index 6fae1f2cb..2c2b0715a 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k005289/k005289.hpp @@ -11,7 +11,8 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +using namespace vgsound_emu; class k005289_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp index d500f091a..ef3af56dd 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class k007232_intf : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp index bca78a1f4..a84dc16a8 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class k053260_intf : public vgsound_emu_core { @@ -31,7 +33,7 @@ class k053260_core : public vgsound_emu_core friend class k053260_intf; // k053260 specific interface private: - const int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction + static constexpr int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction class voice_t : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp index 04326ae6d..bb2e6a1cc 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp @@ -11,24 +11,28 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" #include "../core/vox/vox.hpp" +using namespace vgsound_emu; + class msm6295_core : public vox_core { friend class vgsound_emu_mem_intf; // common memory interface private: // Internal volume table, 9 step - const s32 m_volume_table[9] = {32 /* 0.0dB */, - 22 /* -3.2dB */, - 16 /* -6.0dB */, - 11 /* -9.2dB */, - 8 /* -12.0dB */, - 6 /* -14.5dB */, - 4 /* -18.0dB */, - 3 /* -20.5dB */, - 2 /* -24.0dB */}; // scale out to 5 bit for optimization + static constexpr s32 m_volume_table[9] = { + 32 /* 0.0dB */, + 22 /* -3.2dB */, + 16 /* -6.0dB */, + 11 /* -9.2dB */, + 8 /* -12.0dB */, + 6 /* -14.5dB */, + 4 /* -18.0dB */, + 3 /* -20.5dB */, + 2 /* -24.0dB */}; // scale out to 5 bit for optimization // msm6295 voice classes class voice_t : vox_decoder_t diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp index 1c04d1f36..bbf2720ac 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/n163/n163.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class n163_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp index 8824d2535..12322d84f 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/scc/scc.hpp @@ -12,7 +12,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" + +using namespace vgsound_emu; // shared for SCCs class scc_core : public vgsound_emu_core diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp index ca8f91b53..ffc6f9321 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/template/template.hpp @@ -11,7 +11,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" + +using namespace vgsound_emu; class template_core : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp index dc59120f3..8ff62fead 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.cpp @@ -61,10 +61,10 @@ bool vrcvi_core::alu_t::tick() } // carry handling - bool carry = bitfield(m_host.m_control.shift(), 1) - ? (bitfield(temp, 8, 4) == 0) - : (bitfield(m_host.m_control.shift(), 0) ? (bitfield(temp, 4, 8) == 0) - : (bitfield(temp, 0, 12) == 0)); + const bool carry = bitfield(m_host.m_control.shift(), 1) + ? (bitfield(temp, 8, 4) == 0) + : (bitfield(m_host.m_control.shift(), 0) ? (bitfield(temp, 4, 8) == 0) + : (bitfield(temp, 0, 12) == 0)); if (carry) { m_counter = m_divider.divider(); diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp index f163114c0..d6694aaef 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/vrcvi/vrcvi.hpp @@ -11,7 +11,9 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" + +using namespace vgsound_emu; class vrcvi_intf : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp index 34a4ab99a..37a1895bd 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/x1_010/x1_010.hpp @@ -11,7 +11,10 @@ #pragma once -#include "../core/util.hpp" +#include "../core/core.hpp" +#include "../core/util/mem_intf.hpp" + +using namespace vgsound_emu; class x1_010_core : public vgsound_emu_core { From f714acc8a6935eb30eafc601919fa90460f03427 Mon Sep 17 00:00:00 2001 From: cam900 Date: Sat, 22 Oct 2022 10:13:22 +0900 Subject: [PATCH 57/57] Sync with master --- .../vgsound_emu/src/core/vox/vox.hpp | 4 ++-- .../vgsound_emu/src/k053260/k053260.hpp | 2 +- .../vgsound_emu/src/msm6295/msm6295.hpp | 19 +++++++++---------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp index 2f42e3945..1480ff47d 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/core/vox/vox.hpp @@ -95,8 +95,8 @@ class vox_core : public vgsound_emu_core bool m_loop_saved = false; }; - static constexpr s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; - static constexpr s32 m_step_table[49] = { + const s8 m_index_table[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; + const s32 m_step_table[49] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552}; diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp index a84dc16a8..a616708ba 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k053260/k053260.hpp @@ -33,7 +33,7 @@ class k053260_core : public vgsound_emu_core friend class k053260_intf; // k053260 specific interface private: - static constexpr int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction + const int pan_dir[8] = {-1, 0, 24, 35, 45, 55, 66, 90}; // pan direction class voice_t : public vgsound_emu_core { diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp index bb2e6a1cc..9cf50537e 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/msm6295/msm6295.hpp @@ -23,16 +23,15 @@ class msm6295_core : public vox_core private: // Internal volume table, 9 step - static constexpr s32 m_volume_table[9] = { - 32 /* 0.0dB */, - 22 /* -3.2dB */, - 16 /* -6.0dB */, - 11 /* -9.2dB */, - 8 /* -12.0dB */, - 6 /* -14.5dB */, - 4 /* -18.0dB */, - 3 /* -20.5dB */, - 2 /* -24.0dB */}; // scale out to 5 bit for optimization + const s32 m_volume_table[9] = {32 /* 0.0dB */, + 22 /* -3.2dB */, + 16 /* -6.0dB */, + 11 /* -9.2dB */, + 8 /* -12.0dB */, + 6 /* -14.5dB */, + 4 /* -18.0dB */, + 3 /* -20.5dB */, + 2 /* -24.0dB */}; // scale out to 5 bit for optimization // msm6295 voice classes class voice_t : vox_decoder_t