From 8746d36eace79d754833e036e6b6fd6865419a2b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 14 Jan 2023 23:16:29 -0500 Subject: [PATCH 01/16] finally fix that Windows 32-bit crash --- src/gui/scaling.cpp | 9 +++++---- src/gui/shellScalingStub.h | 36 ++++++++++++++++++++++++++++++++++++ src/main.cpp | 20 ++++++++++++++++++++ 3 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/gui/shellScalingStub.h diff --git a/src/gui/scaling.cpp b/src/gui/scaling.cpp index 7c42a1e33..1b8cfae35 100644 --- a/src/gui/scaling.cpp +++ b/src/gui/scaling.cpp @@ -24,7 +24,8 @@ #ifdef _WIN32 #include -typedef HRESULT (*GDFM)(HMONITOR,int,UINT*,UINT*); +#include "shellScalingStub.h" +typedef HRESULT (WINAPI *GDFM)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); #endif #ifdef __APPLE__ @@ -71,9 +72,9 @@ double getScaleFactor(const char* driverHint) { return 1.0; } - unsigned int dpiX=96; - unsigned int dpiY=96; - HRESULT result=ta_GetDpiForMonitor(disp,0,&dpiX,&dpiY); + UINT dpiX=96; + UINT dpiY=96; + HRESULT result=ta_GetDpiForMonitor(disp,MDT_EFFECTIVE_DPI,&dpiX,&dpiY); if (result!=S_OK) { logW("GetDpiForMonitor failure (%.8x) - no scaling detection available!",result); diff --git a/src/gui/shellScalingStub.h b/src/gui/shellScalingStub.h new file mode 100644 index 000000000..88ddf2f7e --- /dev/null +++ b/src/gui/shellScalingStub.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016 Sebastian Lackner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_SHELLSCALINGAPI_H + +typedef enum MONITOR_DPI_TYPE +{ + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI, +} MONITOR_DPI_TYPE; + +typedef enum PROCESS_DPI_AWARENESS +{ + PROCESS_DPI_UNAWARE, + PROCESS_SYSTEM_DPI_AWARE, + PROCESS_PER_MONITOR_DPI_AWARE +} PROCESS_DPI_AWARENESS; + +#endif /* __WINE_SHELLSCALINGAPI_H */ diff --git a/src/main.cpp b/src/main.cpp index 7d797fcfb..ef335a223 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,10 @@ #include #include #include + +#include "gui/shellScalingStub.h" + +typedef HRESULT (WINAPI *SPDA)(PROCESS_DPI_AWARENESS); #else #include #endif @@ -339,6 +343,22 @@ void reportError(String what) { int main(int argc, char** argv) { initLog(); #ifdef _WIN32 + // 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(PROCESS_PER_MONITOR_DPI_AWARE); + if (result!=S_OK) { + // ??? + } + } + if (!FreeLibrary(shcore)) { + // ??? + } + } + + // co initialize ex HRESULT coResult=CoInitializeEx(NULL,COINIT_MULTITHREADED); if (coResult!=S_OK) { logE("CoInitializeEx failed!"); From a3be1c9af63a743e9b9de68eb58291b5f87599c2 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 14 Jan 2023 23:17:09 -0500 Subject: [PATCH 02/16] CI: re-enable MinGW/Linux builds --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 980062769..11940edad 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,11 +20,11 @@ jobs: config: - { name: 'Windows MSVC x86', os: windows-latest, compiler: msvc, arch: x86 } - { name: 'Windows MSVC x86_64', os: windows-latest, compiler: msvc, arch: x86_64 } - ##- { name: 'Windows MinGW x86', os: ubuntu-20.04, compiler: mingw, arch: x86 } - ##- { name: 'Windows MinGW x86_64', os: ubuntu-20.04, compiler: mingw, arch: x86_64 } + - { name: 'Windows MinGW x86', os: ubuntu-20.04, compiler: mingw, arch: x86 } + - { name: 'Windows MinGW x86_64', os: ubuntu-20.04, compiler: mingw, arch: x86_64 } - { name: 'macOS x86_64', os: macos-latest, arch: x86_64 } - { name: 'macOS ARM', os: macos-latest, arch: arm64 } - ##- { name: 'Linux x86_64', os: ubuntu-18.04, arch: x86_64 } + - { name: 'Linux x86_64', os: ubuntu-18.04, arch: x86_64 } #- { name: 'Linux ARM', os: ubuntu-18.04, arch: armhf } fail-fast: false From cf3e907501baf6c10e3f82fe04420cdef31c9dd2 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 14 Jan 2023 23:33:19 -0500 Subject: [PATCH 03/16] CI: go back to release mode --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 11940edad..9c4b11c46 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ defaults: shell: bash env: - BUILD_TYPE: Debug + BUILD_TYPE: Release jobs: build: From f4d922822a79dd4891614d1adc35e07d2116a913 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 00:01:54 -0500 Subject: [PATCH 04/16] add PCE demo by Fragmare --- demos/pce/Bad_Dudes_Greased_Lightning.fur | Bin 0 -> 4532 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 demos/pce/Bad_Dudes_Greased_Lightning.fur diff --git a/demos/pce/Bad_Dudes_Greased_Lightning.fur b/demos/pce/Bad_Dudes_Greased_Lightning.fur new file mode 100644 index 0000000000000000000000000000000000000000..98209900ed451f5a77c6229a8c1e4de07057e1f0 GIT binary patch literal 4532 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%0DxO}CAT|TPB1Yz5! zsal8CvnfyjN&URG`|rJiE2BHxf-_&riS;1jqoaa7T5$x*O9jx|9ir7VW!EP3Zi2)EYo!#!> zR+4(lTJlye&?kOs+65N5 z>zKcoSog%_%awh(p0hbcwa~%X?WUP z!~stc#!Jok9oK|RkL_kZ$+Gie?C|t&;yg(DgYk9VcdSDg_+mE<$PjajGXXI Date: Sun, 15 Jan 2023 00:40:57 -0500 Subject: [PATCH 05/16] SoundUnit: separate flag register issue #649 --- src/engine/platform/sound/su.cpp | 38 +++++++++++++++----------------- src/engine/platform/sound/su.h | 10 ++++++--- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/engine/platform/sound/su.cpp b/src/engine/platform/sound/su.cpp index 4d98892cc..f7bb24b31 100644 --- a/src/engine/platform/sound/su.cpp +++ b/src/engine/platform/sound/su.cpp @@ -17,13 +17,13 @@ void SoundUnit::NextSample(short* l, short* r) { // run channels for (int i=0; i<8; i++) { - if (chan[i].vol==0 && !chan[i].flags.swvol) { + if (chan[i].vol==0 && !chan[i].flags1.swvol) { fns[i]=0; continue; } - if (chan[i].flags.pcm) { + if (chan[i].flags0.pcm) { ns[i]=pcm[chan[i].pcmpos]; - } else switch (chan[i].flags.shape) { + } else switch (chan[i].flags0.shape) { case 0: ns[i]=(((cycle[i]>>15)&127)>chan[i].duty)*127; break; @@ -47,11 +47,11 @@ void SoundUnit::NextSample(short* l, short* r) { break; } - if (chan[i].flags.ring) { + if (chan[i].flags0.ring) { ns[i]=(ns[i]*ns[(i+1)&7])>>7; } - if (chan[i].flags.pcm) { + if (chan[i].flags0.pcm) { if (chan[i].freq>0x8000) { pcmdec[i]+=0x8000; } else { @@ -62,18 +62,18 @@ void SoundUnit::NextSample(short* l, short* r) { if (chan[i].pcmpos>4)&3) { case 0: cycle[i]+=chan[i].freq*1-(chan[i].freq>>3); @@ -92,7 +92,7 @@ void SoundUnit::NextSample(short* l, short* r) { cycle[i]+=chan[i].freq; } if ((cycle[i]&0xf80000)!=(ocycle[i]&0xf80000)) { - if (chan[i].flags.shape==4) { + if (chan[i].flags0.shape==4) { lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<31); } else { switch ((chan[i].duty>>4)&3) { @@ -114,7 +114,7 @@ void SoundUnit::NextSample(short* l, short* r) { } } } - if (chan[i].flags.restim) { + if (chan[i].flags1.restim) { if (--rcycle[i]<=0) { cycle[i]=0; rcycle[i]=chan[i].restimer; @@ -122,19 +122,18 @@ void SoundUnit::NextSample(short* l, short* r) { } } } - fns[i]=ns[i]*chan[i].vol*(chan[i].flags.pcm?4:2); - if (chan[i].flags.fmode!=0) { + fns[i]=ns[i]*chan[i].vol*(chan[i].flags0.pcm?4:2); + if (chan[i].flags0.fmode!=0) { int ff=chan[i].cutoff; nslow[i]=nslow[i]+(((ff)*nsband[i])>>16); nshigh[i]=fns[i]-nslow[i]-(((256-chan[i].reson)*nsband[i])>>8); nsband[i]=(((ff)*nshigh[i])>>16)+nsband[i]; - fns[i]=(((chan[i].flags.fmode&1)?(nslow[i]):(0))+((chan[i].flags.fmode&2)?(nshigh[i]):(0))+((chan[i].flags.fmode&4)?(nsband[i]):(0))); + fns[i]=(((chan[i].flags0.fmode&1)?(nslow[i]):(0))+((chan[i].flags0.fmode&2)?(nshigh[i]):(0))+((chan[i].flags0.fmode&4)?(nsband[i]):(0))); } nsL[i]=(fns[i]*SCpantabL[(unsigned char)chan[i].pan])>>8; nsR[i]=(fns[i]*SCpantabR[(unsigned char)chan[i].pan])>>8; oldfreq[i]=chan[i].freq; - oldflags[i]=chan[i].flags.flags; - if (chan[i].flags.swvol) { + if (chan[i].flags1.swvol) { if (--swvolt[i]<=0) { swvolt[i]=chan[i].swvol.speed; if (chan[i].swvol.dir) { @@ -174,7 +173,7 @@ void SoundUnit::NextSample(short* l, short* r) { } } } - if (chan[i].flags.swfreq) { + if (chan[i].flags1.swfreq) { if (--swfreqt[i]<=0) { swfreqt[i]=chan[i].swfreq.speed; if (chan[i].swfreq.dir) { @@ -198,7 +197,7 @@ void SoundUnit::NextSample(short* l, short* r) { } } } - if (chan[i].flags.swcut) { + if (chan[i].flags1.swcut) { if (--swcutt[i]<=0) { swcutt[i]=chan[i].swcut.speed; if (chan[i].swcut.dir) { @@ -222,11 +221,11 @@ void SoundUnit::NextSample(short* l, short* r) { } } } - if (chan[i].flags.resosc) { + if (chan[i].flags1.resosc) { cycle[i]=0; rcycle[i]=chan[i].restimer; ocycle[i]=0; - chan[i].flags.resosc=0; + chan[i].flags1.resosc=0; } if (muted[i]) { nsL[i]=0; @@ -377,7 +376,6 @@ void SoundUnit::Reset() { swcutt[i]=1; lfsr[i]=0xaaaa; oldfreq[i]=0; - oldflags[i]=0; pcmdec[i]=0; } dsCounterL=0; diff --git a/src/engine/platform/sound/su.h b/src/engine/platform/sound/su.h index 546acfc9c..528d545b5 100644 --- a/src/engine/platform/sound/su.h +++ b/src/engine/platform/sound/su.h @@ -25,7 +25,6 @@ class SoundUnit { signed char ilFeedback0; signed char ilFeedback1; unsigned short oldfreq[8]; - unsigned short oldflags[8]; unsigned int pcmSize; bool dsOut; short dsCounterL, dsCounterR; @@ -44,12 +43,17 @@ class SoundUnit { signed char vol; signed char pan; union { - unsigned short flags; + unsigned char val; struct { unsigned char shape: 3; unsigned char pcm: 1; unsigned char ring: 1; unsigned char fmode: 3; + }; + } flags0; + union { + unsigned char val; + struct { unsigned char resosc: 1; unsigned char resfilt: 1; unsigned char pcmloop: 1; @@ -59,7 +63,7 @@ class SoundUnit { unsigned char swcut: 1; unsigned char padding: 1; }; - } flags; + } flags1; unsigned short cutoff; unsigned char duty; unsigned char reson; From cb11d3f268003e1143788cfb827204d90c6572b1 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 00:45:31 -0500 Subject: [PATCH 06/16] strict-aliasing........ --- src/engine/safeReader.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/engine/safeReader.cpp b/src/engine/safeReader.cpp index 76e337a3d..428c91502 100644 --- a/src/engine/safeReader.cpp +++ b/src/engine/safeReader.cpp @@ -136,7 +136,9 @@ float SafeReader::readF() { memcpy(&ret,&buf[curSeek],4); curSeek+=4; ret=((ret>>24)|((ret&0xff0000)>>8)|((ret&0xff00)<<8)|((ret&0xff)<<24)); - return *((float*)(&ret)); + float realRet; + memcpy(&realRet,&ret,4); + return realRet; } double SafeReader::readD() { @@ -153,7 +155,9 @@ double SafeReader::readD() { retB[5]=ret[2]; retB[6]=ret[1]; retB[7]=ret[0]; - return *((double*)retB); + double realRet; + memcpy(&realRet,retB,8); + return realRet; } #else short SafeReader::readS() { From 9ada18a57a8d3ec76ea11eabfbc547ba340f0059 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 01:20:31 -0500 Subject: [PATCH 07/16] VGM export: always write stream freq first --- src/engine/engine.h | 2 +- src/engine/vgmOps.cpp | 48 ++++++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index 31edc8c85..ffa97d755 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -442,7 +442,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, bool directStream); + void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, 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); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 9e4557de3..51d477554 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -24,7 +24,7 @@ constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0; -void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, bool directStream) { +void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, bool directStream) { unsigned char baseAddr1=isSecond?0xa0:0x50; unsigned char baseAddr2=isSecond?0x80:0; unsigned short baseAddr2S=isSecond?0x8000:0; @@ -541,14 +541,19 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write 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 (playingSample[streamID]!=write.val) { + pendingFreq[streamID]=write.val; + } else { + DivSample* sample=song.sample[write.val]; + w->writeC(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; + } + playingSample[streamID]=write.val; } } break; @@ -557,11 +562,26 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(streamID); w->writeI(write.val); loopFreq[streamID]=write.val; + if (pendingFreq[streamID]!=-1) { + DivSample* sample=song.sample[pendingFreq[streamID]]; + w->writeC(0x95); + w->writeC(streamID); + w->writeS(pendingFreq[streamID]); // 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; + } + playingSample[streamID]=pendingFreq[streamID]; + pendingFreq[streamID]=-1; + } break; case 2: // stop sample w->writeC(0x94); w->writeC(streamID); loopSample[streamID]=-1; + playingSample[streamID]=-1; + pendingFreq[streamID]=-1; break; case 3: // set sample direction sampleDir[streamID]=write.val; @@ -979,7 +999,9 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p double loopFreq[DIV_MAX_CHANS]; int loopSample[DIV_MAX_CHANS]; bool sampleDir[DIV_MAX_CHANS]; - std::vector chipVol; + int pendingFreq[DIV_MAX_CHANS]; + int playingSample[DIV_MAX_CHANS]; + std::vector chipVol; std::vector delayedWrites[DIV_MAX_CHIPS]; std::vector> sortedWrites; @@ -987,6 +1009,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p loopTimer[i]=0; loopFreq[i]=0; loopSample[i]=-1; + pendingFreq[i]=-1; + playingSample[i]=-1; sampleDir[i]=false; } @@ -1991,7 +2015,7 @@ 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],directStream); + performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,directStream); writeCount++; } writes.clear(); @@ -2031,7 +2055,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p 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); + performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,directStream); writeCount++; } sortedWrites.clear(); From a3d20ac3fd3e866d7251d9209f11659c5f44d3c7 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 01:46:34 -0500 Subject: [PATCH 08/16] WonderSwan: why does this not work --- src/engine/platform/swan.cpp | 22 +++++++++++++++------- src/engine/platform/swan.h | 1 + src/engine/vgmOps.cpp | 2 +- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index f5a2dfb9a..001d2957a 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -22,6 +22,7 @@ #include #define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);}} +#define postWrite(a,v) postDACWrites.emplace(a,v); #define CHIP_DIVIDER 32 @@ -186,7 +187,7 @@ void DivPlatformSwan::tick(bool sysTick) { } } dacRate=((double)chipClock/2)/MAX(1,off*chan[i].freq); - if (dumpWrites) addWrite(0xffff0001,dacRate); + if (dumpWrites) postWrite(0xffff0001,dacRate); } if (chan[i].freq>2048) chan[i].freq=2048; if (chan[i].freq<1) chan[i].freq=1; @@ -217,6 +218,12 @@ void DivPlatformSwan::tick(bool sysTick) { } } rWrite(0x10,sndCtrl); + + while (!postDACWrites.empty()) { + const DivRegWrite& w=postDACWrites.back(); + if (dumpWrites) addWrite(w.addr,w.val); + postDACWrites.pop(); + } } int DivPlatformSwan::dispatch(DivCommand c) { @@ -237,11 +244,11 @@ int DivPlatformSwan::dispatch(DivCommand c) { if (c.value!=DIV_NOTE_NULL) dacSample=ins->amiga.getSample(c.value); if (dacSample<0 || dacSample>=parent->song.sampleLen) { dacSample=-1; - if (dumpWrites) addWrite(0xffff0002,0); + if (dumpWrites) postWrite(0xffff0002,0); break; } else { if (dumpWrites) { - addWrite(0xffff0000,dacSample); + postWrite(0xffff0000,dacSample); } } if (c.value!=DIV_NOTE_NULL) { @@ -260,14 +267,14 @@ int DivPlatformSwan::dispatch(DivCommand c) { dacSample=12*sampleBank+chan[1].note%12; if (dacSample>=parent->song.sampleLen) { dacSample=-1; - if (dumpWrites) addWrite(0xffff0002,0); + if (dumpWrites) postWrite(0xffff0002,0); break; } else { - if (dumpWrites) addWrite(0xffff0000,dacSample); + if (dumpWrites) postWrite(0xffff0000,dacSample); } dacRate=parent->getSample(dacSample)->rate; if (dumpWrites) { - addWrite(0xffff0001,dacRate); + postWrite(0xffff0001,dacRate); } chan[1].active=true; chan[1].keyOn=true; @@ -298,7 +305,7 @@ int DivPlatformSwan::dispatch(DivCommand c) { case DIV_CMD_NOTE_OFF: if (c.chan==1&&pcm) { dacSample=-1; - if (dumpWrites) addWrite(0xffff0002,0); + if (dumpWrites) postWrite(0xffff0002,0); pcm=false; } chan[c.chan].active=false; @@ -463,6 +470,7 @@ int DivPlatformSwan::getRegisterPoolSize() { void DivPlatformSwan::reset() { while (!writes.empty()) writes.pop(); + while (!postDACWrites.empty()) postDACWrites.pop(); memset(regPool,0,128); for (int i=0; i<4; i++) { chan[i]=Channel(); diff --git a/src/engine/platform/swan.h b/src/engine/platform/swan.h index 6f129e6dd..10e769fc4 100644 --- a/src/engine/platform/swan.h +++ b/src/engine/platform/swan.h @@ -51,6 +51,7 @@ class DivPlatformSwan: public DivDispatch { QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {} }; std::queue writes; + std::queue postDACWrites; WSwan* ws; void updateWave(int ch); friend void putDispatchChip(void*,int); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 51d477554..4c82b729a 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -570,7 +570,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write 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; + loopSample[streamID]=pendingFreq[streamID]; } playingSample[streamID]=pendingFreq[streamID]; pendingFreq[streamID]=-1; From 6c5f9886fb25190b96d411658cf61108c69a01c5 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 02:10:24 -0500 Subject: [PATCH 09/16] OPL: fix t/hh per-chan osc not being visib in OPL3 --- src/engine/platform/opl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 4e798c6e5..2c6c15903 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -1509,7 +1509,7 @@ DivMacroInt* DivPlatformOPL::getChanMacroInt(int ch) { } DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) { - if (ch>=18) return NULL; + if (ch>=totalChans) return NULL; if (oplType==3 && ch<12) { if (chan[ch&(~1)].fourOp) { if (ch&1) { From 17cb32fe9eca5683887dc6e1ca8f8ebb5c432086 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 03:54:11 -0500 Subject: [PATCH 10/16] VGM export: improve volumes --- src/engine/vgmOps.cpp | 79 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 4c82b729a..bb8a31cd0 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -883,16 +883,20 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write } #define CHIP_VOL(_id,_mult) { \ - double _vol=fabs((float)song.systemVol[i])*4.0*_mult; \ + double _vol=fabs((float)song.systemVol[i])*256.0*_mult; \ if (_vol<0.0) _vol=0.0; \ if (_vol>32767.0) _vol=32767.0; \ + chipVolSum+=(unsigned int)(_vol/_mult); \ + chipAccounting++; \ chipVol.push_back((_id)|(0x80000000)|(((unsigned int)_vol)<<16)); \ } #define CHIP_VOL_SECOND(_id,_mult) { \ - double _vol=fabs((float)song.systemVol[i])*4.0*_mult; \ + double _vol=fabs((float)song.systemVol[i])*256.0*_mult; \ if (_vol<0.0) _vol=0.0; \ if (_vol>32767.0) _vol=32767.0; \ + chipVolSum+=(unsigned int)(_vol/_mult); \ + chipAccounting++; \ chipVol.push_back((_id)|(0x80000100)|(((unsigned int)_vol)<<16)); \ } @@ -977,6 +981,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p int hasLynx=0; int howManyChips=0; + int chipVolSum=0; + int chipAccounting=0; int loopPos=-1; int loopTick=-1; @@ -1040,7 +1046,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_SMS: if (!hasSN) { hasSN=disCont[i].dispatch->chipClock; - CHIP_VOL(0,1.0); + CHIP_VOL(0,2.0); willExport[i]=true; switch (song.systemFlags[i].getInt("chipType",0)) { case 1: // real SN @@ -1059,7 +1065,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } else if (!(hasSN&0x40000000)) { isSecond[i]=true; willExport[i]=true; - CHIP_VOL_SECOND(0,1.0); + CHIP_VOL_SECOND(0,2.0); hasSN|=0x40000000; howManyChips++; } @@ -1067,9 +1073,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_GB: if (!hasGB) { hasGB=disCont[i].dispatch->chipClock; + CHIP_VOL(19,0.75); willExport[i]=true; } else if (!(hasGB&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(19,0.75); willExport[i]=true; hasGB|=0x40000000; howManyChips++; @@ -1078,10 +1086,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_PCE: if (!hasPCE) { hasPCE=disCont[i].dispatch->chipClock; + CHIP_VOL(27,0.98); willExport[i]=true; writePCESamples=true; } else if (!(hasPCE&0x40000000)) { isSecond[i]=true; + CHIP_VOL(27,0.98); willExport[i]=true; hasPCE|=0x40000000; howManyChips++; @@ -1090,10 +1100,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_NES: if (!hasNES) { hasNES=disCont[i].dispatch->chipClock; + CHIP_VOL(20,1.7); willExport[i]=true; writeNESSamples=true; } else if (!(hasNES&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(20,1.7); willExport[i]=true; hasNES|=0x40000000; howManyChips++; @@ -1103,10 +1115,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_SEGAPCM_COMPAT: if (!hasSegaPCM) { hasSegaPCM=4000000; + CHIP_VOL(4,0.67); willExport[i]=true; writeSegaPCM=1; } else if (!(hasSegaPCM&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(4,0.67); willExport[i]=true; writeSegaPCM=2; hasSegaPCM|=0x40000000; @@ -1116,10 +1130,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_X1_010: if (!hasX1) { hasX1=disCont[i].dispatch->chipClock; + CHIP_VOL(38,0.5); willExport[i]=true; writeX1010[0]=disCont[i].dispatch; } else if (!(hasX1&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(38,0.5); willExport[i]=true; writeX1010[1]=disCont[i].dispatch; hasX1|=0x40000000; @@ -1134,10 +1150,14 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_YM2610B_EXT: if (!hasOPNB) { hasOPNB=disCont[i].dispatch->chipClock; + CHIP_VOL(8,1.0); + CHIP_VOL(0x88,1.25); willExport[i]=true; writeADPCM_OPNB[0]=disCont[i].dispatch; } else if (!(hasOPNB&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(8,1.0); + CHIP_VOL_SECOND(0x88,1.25); willExport[i]=true; writeADPCM_OPNB[1]=disCont[i].dispatch; hasOPNB|=0x40000000; @@ -1182,9 +1202,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (hasStereo && song.systemFlags[i].getBool("stereo",false)) { ayFlags|=0x80; } + CHIP_VOL(18,1.0); willExport[i]=true; } else if (!(hasAY&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(18,1.0); willExport[i]=true; hasAY|=0x40000000; howManyChips++; @@ -1194,9 +1216,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_SAA1099: if (!hasSAA) { hasSAA=disCont[i].dispatch->chipClock; + CHIP_VOL(35,1.0); willExport[i]=true; } else if (!(hasSAA&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(35,1.0); willExport[i]=true; hasSAA|=0x40000000; howManyChips++; @@ -1208,10 +1232,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_YM2612_DUALPCM_EXT: if (!hasOPN2) { hasOPN2=disCont[i].dispatch->chipClock; + CHIP_VOL(2,0.8); willExport[i]=true; writeDACSamples=true; } else if (!(hasOPN2&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(2,0.8); willExport[i]=true; hasOPN2|=0x40000000; howManyChips++; @@ -1220,9 +1246,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_YM2151: if (!hasOPM) { hasOPM=disCont[i].dispatch->chipClock; + CHIP_VOL(3,1.0); willExport[i]=true; } else if (!(hasOPM&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(3,1.0); willExport[i]=true; hasOPM|=0x40000000; howManyChips++; @@ -1233,10 +1261,14 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (!hasOPN) { hasOPN=disCont[i].dispatch->chipClock; willExport[i]=true; + CHIP_VOL(6,1.0); + CHIP_VOL(0x86,1.7); writeDACSamples=true; } else if (!(hasOPN&0x40000000)) { isSecond[i]=true; willExport[i]=true; + CHIP_VOL_SECOND(6,1.0); + CHIP_VOL_SECOND(0x86,1.7); hasOPN|=0x40000000; howManyChips++; } @@ -1245,10 +1277,14 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_YM2608_EXT: if (!hasOPNA) { hasOPNA=disCont[i].dispatch->chipClock; + CHIP_VOL(7,1.0); + CHIP_VOL(0x87,1.3); willExport[i]=true; writeADPCM_OPNA[0]=disCont[i].dispatch; } else if (!(hasOPNA&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(7,1.0); + CHIP_VOL_SECOND(0x87,1.3); willExport[i]=true; writeADPCM_OPNA[1]=disCont[i].dispatch; hasOPNA|=0x40000000; @@ -1260,9 +1296,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_VRC7: if (!hasOPLL) { hasOPLL=disCont[i].dispatch->chipClock; + CHIP_VOL(1,1.6); willExport[i]=true; } else if (!(hasOPLL&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(1,1.6); willExport[i]=true; hasOPLL|=0x40000000; howManyChips++; @@ -1285,9 +1323,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_POKEY: if (!hasPOKEY) { hasPOKEY=disCont[i].dispatch->chipClock; + CHIP_VOL(30,0.8); willExport[i]=true; } else if (!(hasPOKEY&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(30,0.8); willExport[i]=true; hasPOKEY|=0x40000000; howManyChips++; @@ -1310,10 +1350,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p // However I think it it not necessary because old VGM players will still // not be able to handle the 64kb sample bank trick hasQSound=disCont[i].dispatch->chipClock; + CHIP_VOL(31,1.0); willExport[i]=true; writeQSound[0]=disCont[i].dispatch; } else if (!(hasQSound&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(31,1.0); willExport[i]=false; writeQSound[1]=disCont[i].dispatch; addWarning("dual QSound is not supported by the VGM format"); @@ -1322,6 +1364,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_SWAN: if (!hasSwan) { hasSwan=disCont[i].dispatch->chipClock; + CHIP_VOL(33,1.0); willExport[i]=true; // funny enough, VGM doesn't have support for WSC's sound DMA by design // so DAC stream it goes @@ -1329,6 +1372,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p writeDACSamples=true; } else if (!(hasSwan&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(33,1.0); willExport[i]=true; hasSwan|=0x40000000; howManyChips++; @@ -1337,9 +1381,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_VBOY: if (!hasVSU) { hasVSU=disCont[i].dispatch->chipClock; + CHIP_VOL(34,0.72); willExport[i]=true; } else if (!(hasVSU&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(34,0.72); willExport[i]=true; hasVSU|=0x40000000; howManyChips++; @@ -1349,9 +1395,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_OPL_DRUMS: if (!hasOPL) { hasOPL=disCont[i].dispatch->chipClock; + CHIP_VOL(9,1.0); willExport[i]=true; } else if (!(hasOPL&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(9,1.0); willExport[i]=true; hasOPL|=0x40000000; howManyChips++; @@ -1361,10 +1409,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_Y8950_DRUMS: if (!hasY8950) { hasY8950=disCont[i].dispatch->chipClock; + CHIP_VOL(11,1.0); willExport[i]=true; writeADPCM_Y8950[0]=disCont[i].dispatch; } else if (!(hasY8950&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(11,1.0); willExport[i]=true; writeADPCM_Y8950[1]=disCont[i].dispatch; hasY8950|=0x40000000; @@ -1375,9 +1425,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_OPL2_DRUMS: if (!hasOPL2) { hasOPL2=disCont[i].dispatch->chipClock; + CHIP_VOL(10,1.0); willExport[i]=true; } else if (!(hasOPL2&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(10,1.0); willExport[i]=true; hasOPL2|=0x40000000; howManyChips++; @@ -1387,9 +1439,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_OPL3_DRUMS: if (!hasOPL3) { hasOPL3=disCont[i].dispatch->chipClock; + CHIP_VOL(12,1.0); willExport[i]=true; } else if (!(hasOPL3&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(12,1.0); willExport[i]=true; hasOPL3|=0x40000000; howManyChips++; @@ -1402,9 +1456,11 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (song.system[i]==DIV_SYSTEM_SCC_PLUS) { hasK051649|=0x80000000; } + CHIP_VOL(25,1.0); willExport[i]=true; } else if (!(hasK051649&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(25,1.0); willExport[i]=true; hasK051649|=0x40000000; if (song.system[i]==DIV_SYSTEM_SCC_PLUS) { @@ -1416,10 +1472,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_YMZ280B: if (!hasZ280) { hasZ280=disCont[i].dispatch->chipClock; + CHIP_VOL(15,0.72); willExport[i]=true; writeZ280[0]=disCont[i].dispatch; } else if (!(hasZ280&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(15,0.72); willExport[i]=true; writeZ280[1]=disCont[i].dispatch; hasZ280|=0x40000000; @@ -1435,11 +1493,13 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p if (!hasRFC1) { hasRFC1=disCont[i].dispatch->chipClock; isSecond[i]=true; + CHIP_VOL(16,1.6); willExport[i]=true; writeRF5C68[1]=disCont[i].dispatch; } } else if (!hasRFC) { hasRFC=disCont[i].dispatch->chipClock; + CHIP_VOL(5,1.6); willExport[i]=true; writeRF5C68[0]=disCont[i].dispatch; } @@ -1447,10 +1507,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_MSM6295: if (!hasOKIM6295) { hasOKIM6295=disCont[i].dispatch->chipClock; + CHIP_VOL(24,1.0); willExport[i]=true; writeMSM6295[0]=disCont[i].dispatch; } else if (!(hasOKIM6295&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(24,1.0); willExport[i]=true; writeMSM6295[1]=disCont[i].dispatch; hasOKIM6295|=0x40000000; @@ -1460,10 +1522,12 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_GA20: if (!hasGA20) { hasGA20=disCont[i].dispatch->chipClock; + CHIP_VOL(40,0.4); willExport[i]=true; writeGA20[0]=disCont[i].dispatch; } else if (!(hasGA20&0x40000000)) { isSecond[i]=true; + CHIP_VOL_SECOND(40,0.4); willExport[i]=true; writeGA20[1]=disCont[i].dispatch; hasGA20|=0x40000000; @@ -1473,7 +1537,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p case DIV_SYSTEM_T6W28: if (!hasSN) { hasSN=0xc0000000|disCont[i].dispatch->chipClock; - CHIP_VOL(0,1.0); + CHIP_VOL(0,2.0); snNoiseConfig=3; snNoiseSize=15; willExport[i]=true; @@ -1548,8 +1612,9 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p w->writeC(0); // OPN w->writeC(0); // OPNA } - if (version>=0x160) { - int calcVolume=32.0*(log(song.masterVol)/log(2.0)); + if (version>=0x160) { // global volume + double abnormalVol=song.masterVol*(double)chipVolSum/(256.0*MAX(1,chipAccounting)); + int calcVolume=32.0*(log(abnormalVol)/log(2.0)); if (calcVolume<-63) calcVolume=-63; if (calcVolume>192) calcVolume=192; w->writeC(calcVolume&0xff); // volume From 1ab80379e125c574d40f26e2830d317377cb583f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 04:32:47 -0500 Subject: [PATCH 11/16] VGM export: fix wrong loop size --- 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 bb8a31cd0..6ac4c2c10 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -2253,7 +2253,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p w->writeI(0); } else { w->writeI(loopPos-0x1c); - w->writeI(tickCount-loopTick-1); + w->writeI(tickCount-loopTick); } } else { w->writeI(0); From 1a27bf3373eee870aa9f0b70fac3081c707da206 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 14:12:23 -0500 Subject: [PATCH 12/16] GUI: fix KSL values 1/2 being swapped in OPL --- src/gui/insEdit.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index c72958ed9..7ac353455 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -352,6 +352,10 @@ const int detuneUnmap[2][11]={ {0, 0, 0, 3, 4, 5, 6, 7, 2, 1, 0} }; +const int kslMap[4]={ + 0, 2, 1, 3 +}; + // do not change these! // anything other than a checkbox will look ugly! // @@ -2778,7 +2782,11 @@ void FurnaceGUI::drawInsEdit() { if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPZ || ins->type==DIV_INS_OPM) { P(CWVSliderScalar("##RS",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.rs,&_ZERO,&_THREE)); } else { - P(CWVSliderScalar("##KSL",ImVec2(20.0f*dpiScale,sliderHeight),ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); + int ksl=ins->type==DIV_INS_OPLL?op.ksl:kslMap[op.ksl&3]; + if (CWVSliderInt("##KSL",ImVec2(20.0f*dpiScale,sliderHeight),&ksl,0,3)) { + op.ksl=(ins->type==DIV_INS_OPLL?ksl:kslMap[ksl&3]); + PARAMETER; + } } if (ins->type==DIV_INS_OPZ) { @@ -3226,7 +3234,7 @@ void FurnaceGUI::drawInsEdit() { break; case DIV_INS_OPL: - case DIV_INS_OPL_DRUMS: + case DIV_INS_OPL_DRUMS: { // waveform drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); @@ -3268,9 +3276,14 @@ void FurnaceGUI::drawInsEdit() { ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); snprintf(tempID,1024,"%s: %%d",FM_NAME(FM_KSL)); - P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE,tempID)); rightClickable + int ksl=kslMap[op.ksl&3]; + if (CWSliderInt("##KSL",&ksl,0,3,tempID)) { + op.ksl=kslMap[ksl&3]; + PARAMETER; + } rightClickable break; + } case DIV_INS_OPZ: { // waveform drawWaveform(op.ws&7,ins->type==DIV_INS_OPZ,ImVec2(waveWidth,waveHeight)); @@ -3613,7 +3626,11 @@ void FurnaceGUI::drawInsEdit() { ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_RS)); } else { - P(CWSliderScalar("##KSL",ImGuiDataType_U8,&op.ksl,&_ZERO,&_THREE)); rightClickable + int ksl=ins->type==DIV_INS_OPLL?op.ksl:kslMap[op.ksl&3]; + if (CWSliderInt("##KSL",&ksl,0,3)) { + op.ksl=(ins->type==DIV_INS_OPLL?ksl:kslMap[ksl&3]); + PARAMETER; + } rightClickable ImGui::TableNextColumn(); ImGui::Text("%s",FM_NAME(FM_KSL)); } From 3174638120ffe738d25b66347866a4934f9dff06 Mon Sep 17 00:00:00 2001 From: brickblock369 <59150779+brickblock369@users.noreply.github.com> Date: Sun, 15 Jan 2023 12:44:34 -0800 Subject: [PATCH 13/16] Request to add another OPL3 instrument to the repo (#928) * Adding another OPL instrument * Adding another OPL instrument Updated the SL from 6 to 5. --- instruments/OPL/2-OP OPL3 Slap Bass.fui | Bin 0 -> 101 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 instruments/OPL/2-OP OPL3 Slap Bass.fui diff --git a/instruments/OPL/2-OP OPL3 Slap Bass.fui b/instruments/OPL/2-OP OPL3 Slap Bass.fui new file mode 100644 index 0000000000000000000000000000000000000000..fb8f1c1439f61f6e8eb153f9cc640886b50bcda1 GIT binary patch literal 101 zcmZ?s^b2lf;A8M}RAVsG^$$?+5AZQo2+m0?P;g2tE>_U+O-wGzFIGs+OH9g1O;OZj zaPt*m_{7S<5XH;y=@7!e5XivK=HmKQMg~SsejzA}h4DWC5q20> literal 0 HcmV?d00001 From 6834b3b7dbff20488a6b46918b62d1c91ed3b82b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 17:27:16 -0500 Subject: [PATCH 14/16] maybe fix sample corruption when resampling 8-bit --- src/engine/sample.cpp | 46 +++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 08dee993d..c9a313461 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -827,18 +827,15 @@ bool DivSample::resampleBlep(double r) { unsigned int posInt=0; double factor=r/(double)rate; float* sincITable=DivFilterTables::getSincIntegralTable(); - float s[16]; - memset(s,0,16*sizeof(float)); + float* floatData=new float[finalCount]; + memset(floatData,0,finalCount*sizeof(float)); if (depth==DIV_SAMPLE_DEPTH_16BIT) { memset(data16,0,finalCount*sizeof(short)); for (int i=0; i32767) result=32767; - data16[i]=result; + data16[i]=oldData16[posInt]; } posFrac+=1.0; @@ -853,28 +850,25 @@ bool DivSample::resampleBlep(double r) { for (int j=0; j<8; j++) { if (i-j>0) { - float result=data16[i-j]+t1[j]*-delta; - if (result<-32768) result=-32768; - if (result>32767) result=32767; - data16[i-j]=result; + floatData[i-j]+=t1[j]*-delta; } if (i+j+132767) result=32767; - data16[i+j+1]=result; + floatData[i+j+1]+=t2[j]*delta; } } } } + for (int i=0; i32767) result=32767; + data16[i]=round(result); + } } else if (depth==DIV_SAMPLE_DEPTH_8BIT) { memset(data8,0,finalCount); for (int i=0; i127) result=127; - data8[i]=result; + data8[i]=oldData8[posInt]; } posFrac+=1.0; @@ -889,20 +883,20 @@ bool DivSample::resampleBlep(double r) { for (int j=0; j<8; j++) { if (i-j>0) { - float result=data8[i-j]+t1[j]*-delta; - if (result<-128) result=-128; - if (result>127) result=127; - data8[i-j]=result; + floatData[i-j]+=t1[j]*-delta; } if (i+j+1127) result=127; - data8[i+j+1]=result; + floatData[i+j+1]+=t2[j]*delta; } } } } + for (int i=0; i127) result=127; + data16[i]=round(result); + } } RESAMPLE_END; From 3370e91aad95170d7d54f9cfd719420d196ba158 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 17:28:47 -0500 Subject: [PATCH 15/16] MEMORY LEAK --- src/engine/sample.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index c9a313461..5df46fab1 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -898,6 +898,7 @@ bool DivSample::resampleBlep(double r) { data16[i]=round(result); } } + delete[] floatData; RESAMPLE_END; return true; From bf2ef2742a160ffc38c1e5f1eca1ba738ca7eb0e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 18:05:48 -0500 Subject: [PATCH 16/16] YM2612: fix forceIns after sample --- src/engine/platform/genesis.cpp | 4 +++- src/engine/platform/genesisext.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index b547181da..5131afd96 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -586,7 +586,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { } } if (c.chan>=5 && chan[c.chan].dacMode) { - if (skipRegisterWrites) break; + //if (skipRegisterWrites) break; if (ins->type==DIV_INS_AMIGA) { // Furnace mode if (c.value!=DIV_NOTE_NULL) chan[c.chan].dacSample=ins->amiga.getSample(c.value); if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) { @@ -1122,6 +1122,8 @@ void DivPlatformGenesis::forceIns() { } } if (chan[5].dacMode) { + chan[5].dacSample=-1; + chan[6].dacSample=-1; rWrite(0x2b,0x80); } immWrite(0x22,lfoValue); diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 4eb34bc23..8e1e7d127 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -677,6 +677,8 @@ void DivPlatformGenesisExt::forceIns() { } } if (chan[5].dacMode) { + chan[5].dacSample=-1; + chan[6].dacSample=-1; rWrite(0x2b,0x80); } immWrite(0x22,lfoValue);