diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6c05127c..95b3229f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -225,6 +225,9 @@ jobs: fi elif [ '${{ matrix.config.compiler }}' == 'mingw' ]; then CMAKE_EXTRA_ARGS+=('-DCMAKE_TOOLCHAIN_FILE=scripts/Cross-MinGW-${{ steps.windows-identify.outputs.mingw-target }}.cmake') + if [ '${{ matrix.config.arch }}' == 'x86' ]; then + CMAKE_EXTRA_ARGS+=('-DSUPPORT_XP=ON') + fi elif [ '${{ runner.os }}' == 'macOS' ]; then if [ '${{ matrix.config.arch }}' == 'arm64' ]; then CMAKE_EXTRA_ARGS+=('-DCMAKE_OSX_DEPLOYMENT_TARGET="11.0"' '-DCMAKE_OSX_ARCHITECTURES=arm64') diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e9481a0..c8c7372c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ option(SYSTEM_LIBSNDFILE "Use a system-installed version of libsndfile instead o option(SYSTEM_RTMIDI "Use a system-installed version of RtMidi instead of the vendored one" OFF) option(SYSTEM_ZLIB "Use a system-installed version of zlib instead of the vendored one" OFF) option(SYSTEM_SDL2 "Use a system-installed version of SDL2 instead of the vendored one" ${SYSTEM_SDL2_DEFAULT}) +option(SUPPORT_XP "Build a Windows XP-compatible binary" OFF) option(WARNINGS_ARE_ERRORS "Whether warnings in furnace's C++ code should be treated as errors" OFF) option(WITH_DEMOS "Install demo songs" ON) option(WITH_INSTRUMENTS "Install instruments" ON) @@ -623,7 +624,7 @@ src/gui/volMeter.cpp src/gui/gui.cpp ) -if (WIN32 AND (MSVC OR CMAKE_SIZEOF_VOID_P EQUAL 8)) +if (WIN32 AND NOT SUPPORT_XP) list(APPEND GUI_SOURCES extern/nfd-modified/src/nfd_common.cpp) list(APPEND GUI_SOURCES extern/nfd-modified/src/nfd_win.cpp) endif() @@ -708,7 +709,7 @@ if (WIN32) list(APPEND DEPENDENCIES_LIBRARIES -static) endif() # support Windows XP - if (CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT MSVC) + if (SUPPORT_XP) list(APPEND DEPENDENCIES_DEFINES "_WIN32_WINNT=0x0501") endif() elseif (APPLE) diff --git a/README.md b/README.md index 3a27c23b..4da5e593 100644 --- a/README.md +++ b/README.md @@ -210,6 +210,7 @@ Available options: | `SYSTEM_RTMIDI` | `OFF` | Use a system-installed version of RtMidi instead of the vendored one | | `SYSTEM_ZLIB` | `OFF` | Use a system-installed version of zlib instead of the vendored one | | `SYSTEM_SDL2` | `OFF` | Use a system-installed version of SDL2 instead of the vendored one | +| `SUPPORT_XP` | `OFF` | Build a Windows XP-compatible binary | | `WARNINGS_ARE_ERRORS` | `OFF` (but consider enabling this & reporting any errors that arise from it!) | Whether warnings in furnace's C++ code should be treated as errors | | `WITH_DEMOS` | `ON` | Install demo songs on `make install` | | `WITH_INSTRUMENTS` | `ON` | Install demo instruments on `make install` | diff --git a/demos/genesis/laidback.fur b/demos/genesis/laidback.fur new file mode 100644 index 00000000..2edd201c Binary files /dev/null and b/demos/genesis/laidback.fur differ diff --git a/demos/genesis/last_chiptune.fur b/demos/genesis/last_chiptune.fur new file mode 100644 index 00000000..7f38f61a Binary files /dev/null and b/demos/genesis/last_chiptune.fur differ diff --git a/demos/genesis/louder.fur b/demos/genesis/louder.fur new file mode 100644 index 00000000..81c14738 Binary files /dev/null and b/demos/genesis/louder.fur differ diff --git a/demos/genesis/mummy_in_the_pyramid.fur b/demos/genesis/mummy_in_the_pyramid.fur new file mode 100644 index 00000000..d36533c7 Binary files /dev/null and b/demos/genesis/mummy_in_the_pyramid.fur differ diff --git a/demos/genesis/my_problem.fur b/demos/genesis/my_problem.fur new file mode 100644 index 00000000..22c2c71a Binary files /dev/null and b/demos/genesis/my_problem.fur differ diff --git a/demos/x16/Cafe - 010 Editor 2.0crk.fur b/demos/x16/Cafe - 010 Editor 2.0crk.fur deleted file mode 100644 index 339e7238..00000000 Binary files a/demos/x16/Cafe - 010 Editor 2.0crk.fur and /dev/null differ diff --git a/demos/x16/Cafe - 010 Editor 2.0kg.fur b/demos/x16/Cafe - 010 Editor 2.0kg.fur new file mode 100644 index 00000000..6533a384 Binary files /dev/null and b/demos/x16/Cafe - 010 Editor 2.0kg.fur differ diff --git a/extern/pfd-fixed/portable-file-dialogs.h b/extern/pfd-fixed/portable-file-dialogs.h index fc6df0a1..8e5ca507 100644 --- a/extern/pfd-fixed/portable-file-dialogs.h +++ b/extern/pfd-fixed/portable-file-dialogs.h @@ -54,14 +54,16 @@ #include // std::chrono // Versions of mingw64 g++ up to 9.3.0 do not have a complete IFileDialog +// we don't use PFD on Windows anyway #ifndef PFD_HAS_IFILEDIALOG -# define PFD_HAS_IFILEDIALOG 1 -# if (defined __MINGW64__ || defined __MINGW32__) && defined __GXX_ABI_VERSION -# if __GXX_ABI_VERSION <= 1014 -# undef PFD_HAS_IFILEDIALOG -# define PFD_HAS_IFILEDIALOG 0 -# endif -# endif +#define PFD_HAS_IFILEDIALOG 0 +//# define PFD_HAS_IFILEDIALOG 1 +//# if (defined __MINGW64__ || defined __MINGW32__) && defined __GXX_ABI_VERSION +//# if __GXX_ABI_VERSION <= 1014 +//# undef PFD_HAS_IFILEDIALOG +//# define PFD_HAS_IFILEDIALOG 0 +//# endif +//# endif #endif namespace pfd diff --git a/scripts/release-win32.sh b/scripts/release-win32.sh index 7b3c76d7..c763eed5 100755 --- a/scripts/release-win32.sh +++ b/scripts/release-win32.sh @@ -15,7 +15,7 @@ fi cd win32build # TODO: potential Arch-ism? -i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type -Werror" -DBUILD_SHARED_LIBS=OFF .. || exit 1 +i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type -Werror" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=ON .. || exit 1 make -j8 || exit 1 i686-w64-mingw32-strip -s furnace.exe || exit 1 diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index d30e1fb9..433e288f 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -206,7 +206,8 @@ bool DivInstrumentSNES::operator==(const DivInstrumentSNES& other) { _C(a) && _C(d) && _C(s) && - _C(r) + _C(r) && + _C(d2) ); } diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 52414799..0ecd6ba4 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -224,7 +224,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) { } } } else { - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); chan[c.chan].useWave=false; } if (c.value!=DIV_NOTE_NULL) { diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 25a4cd1a..bc3abc3c 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -404,7 +404,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { if (chan[c.chan].nextPSGMode.dac) { if (skipRegisterWrites) break; if (!parent->song.disableSampleMacro && (ins->type==DIV_INS_AMIGA || ins->amiga.useSample)) { - chan[c.chan].dac.sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].dac.sample=ins->amiga.getSample(c.value); if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) { chan[c.chan].dac.sample=-1; if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0); diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index c00b3b91..5d8cbc13 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -405,7 +405,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { if (chan[c.chan].nextPSGMode.dac) { if (skipRegisterWrites) break; if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) { - chan[c.chan].dac.sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].dac.sample=ins->amiga.getSample(c.value); if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) { chan[c.chan].dac.sample=-1; if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0); diff --git a/src/engine/platform/ga20.cpp b/src/engine/platform/ga20.cpp index 84131313..bd3c79df 100644 --- a/src/engine/platform/ga20.cpp +++ b/src/engine/platform/ga20.cpp @@ -202,7 +202,7 @@ int DivPlatformGA20::dispatch(DivCommand c) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA); chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:255; - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); } diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 510b4e79..62151b5e 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -346,6 +346,12 @@ void DivPlatformGenesis::tick(bool sysTick) { chan[i].freqChanged=true; } + if (i>=5 && chan[i].std.phaseReset.had) { + if (chan[i].std.phaseReset.val==1 && chan[i].furnaceDac) { + chan[i].dacPos=0; + } + } + if (i>=6) continue; if (chan[i].std.phaseReset.had) { @@ -582,7 +588,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) { if (c.chan>=5 && chan[c.chan].dacMode) { if (skipRegisterWrites) break; if (ins->type==DIV_INS_AMIGA) { // Furnace mode - chan[c.chan].dacSample=ins->amiga.getSample(c.value); + 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) { chan[c.chan].dacSample=-1; if (dumpWrites) addWrite(0xffff0002,0); diff --git a/src/engine/platform/k007232.cpp b/src/engine/platform/k007232.cpp index ce15f115..58304553 100644 --- a/src/engine/platform/k007232.cpp +++ b/src/engine/platform/k007232.cpp @@ -274,7 +274,7 @@ int DivPlatformK007232::dispatch(DivCommand c) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA); chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:15; - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); } diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 1f104e69..3af5dbd8 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -264,7 +264,7 @@ int DivPlatformLynx::dispatch(DivCommand c) { chan[c.chan].baseFreq=NOTE_PERIODIC(c.value); if (chan[c.chan].pcm) { chan[c.chan].sampleBaseFreq=NOTE_FREQUENCY(c.value); - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); chan[c.chan].sampleAccum=0; chan[c.chan].samplePos=0; } diff --git a/src/engine/platform/mmc5.cpp b/src/engine/platform/mmc5.cpp index aafa262e..a00dd771 100644 --- a/src/engine/platform/mmc5.cpp +++ b/src/engine/platform/mmc5.cpp @@ -176,7 +176,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) { if (c.chan==2) { // PCM DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD); if (ins->type==DIV_INS_AMIGA) { - dacSample=ins->amiga.getSample(c.value); + 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); diff --git a/src/engine/platform/msm6258.cpp b/src/engine/platform/msm6258.cpp index 2d38e6f7..32fe24cc 100644 --- a/src/engine/platform/msm6258.cpp +++ b/src/engine/platform/msm6258.cpp @@ -150,7 +150,7 @@ int DivPlatformMSM6258::dispatch(DivCommand c) { if (!chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } - sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) sample=ins->amiga.getSample(c.value); samplePos=0; if (sample>=0 && samplesong.sampleLen) { //DivSample* s=parent->getSample(chan[c.chan].sample); diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index 292229a1..2423167f 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -139,7 +139,7 @@ int DivPlatformMSM6295::dispatch(DivCommand c) { if (!chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { //DivSample* s=parent->getSample(chan[c.chan].sample); if (c.value!=DIV_NOTE_NULL) { diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index a46a6d3f..d0cae5ec 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -360,7 +360,7 @@ int DivPlatformNES::dispatch(DivCommand c) { if (c.chan==4) { // PCM DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD); if (ins->type==DIV_INS_AMIGA) { - dacSample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) dacSample=ins->amiga.getSample(c.value); if (dacSample<0 || dacSample>=parent->song.sampleLen) { dacSample=-1; if (dumpWrites && !dpcmMode) addWrite(0xffff0002,0); diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index 0b4e8619..5af5de8c 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -690,7 +690,7 @@ int DivPlatformOPL::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].vol; immWrite(18,chan[c.chan].outVol); } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(8,0); diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 47a8c0c5..3d9c0aee 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -278,7 +278,7 @@ int DivPlatformPCE::dispatch(DivCommand c) { if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) { chan[c.chan].furnaceDac=true; if (skipRegisterWrites) break; - chan[c.chan].dacSample=ins->amiga.getSample(c.value); + 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) { chan[c.chan].dacSample=-1; if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0); diff --git a/src/engine/platform/pcmdac.cpp b/src/engine/platform/pcmdac.cpp index 53416456..abcdd39f 100644 --- a/src/engine/platform/pcmdac.cpp +++ b/src/engine/platform/pcmdac.cpp @@ -250,7 +250,7 @@ int DivPlatformPCMDAC::dispatch(DivCommand c) { } } } else { - chan[0].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[0].sample=ins->amiga.getSample(c.value); chan[0].useWave=false; } if (c.value!=DIV_NOTE_NULL) { diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index 7ec29357..bc9e0f2a 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -323,14 +323,14 @@ void DivPlatformQSound::tick(bool sysTick) { if (i<16) { qsound_end = offPCM[chan[i].sample] + length + 15; } else { - qsound_end = offBS[chan[i].sample] + length + 15; + qsound_end = offBS[chan[i].sample] + (length>>1) + 15; } qsound_loop = 15; } else { if (i<16) { qsound_end = offPCM[chan[i].sample] + length; } else { - qsound_end = offBS[chan[i].sample] + length; + qsound_end = offBS[chan[i].sample] + (length>>1); } qsound_loop = length - loopStart; } @@ -428,6 +428,9 @@ void DivPlatformQSound::tick(bool sysTick) { } else { rWrite(q1a_vol_map[i-16],0); rWrite(Q1A_KEYON+(i-16),0); + rWrite(q1a_end_map[i-16], 1); + rWrite(q1a_start_map[i-16], 0); + rWrite(Q1A_KEYON+(i-16),1); } } else if (chan[i].active) { //logV("ch %d frequency set to %04x, off=%f, note=%d, %04x!",i,chan[i].freq,off,chan[i].note,QS_NOTE_FREQUENCY(chan[i].note)); @@ -447,7 +450,7 @@ int DivPlatformQSound::dispatch(DivCommand c) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA); chan[c.chan].isNewQSound=(ins->type==DIV_INS_QSOUND); - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=QS_NOTE_FREQUENCY(c.value); } diff --git a/src/engine/platform/rf5c68.cpp b/src/engine/platform/rf5c68.cpp index 58732f49..bf87ce76 100644 --- a/src/engine/platform/rf5c68.cpp +++ b/src/engine/platform/rf5c68.cpp @@ -180,7 +180,7 @@ int DivPlatformRF5C68::dispatch(DivCommand c) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA); chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:255; - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); } diff --git a/src/engine/platform/segapcm.cpp b/src/engine/platform/segapcm.cpp index ccc9f48b..a206de5c 100644 --- a/src/engine/platform/segapcm.cpp +++ b/src/engine/platform/segapcm.cpp @@ -133,9 +133,9 @@ void DivPlatformSegaPCM::tick(bool sysTick) { chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64; if (!parent->song.oldArpStrategy) { if (chan[i].fixedArp) { - chan[i].freq=(chan[i].baseNoteOverride<<7)+(chan[i].pitch>>1)-64+chan[i].pitch2; + chan[i].freq=(chan[i].baseNoteOverride<<6)+(chan[i].pitch>>1)-64+chan[i].pitch2; } else { - chan[i].freq+=chan[i].arpOff<<7; + chan[i].freq+=chan[i].arpOff<<6; } } if (chan[i].furnacePCM) { @@ -216,7 +216,7 @@ int DivPlatformSegaPCM::dispatch(DivCommand c) { if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SEGAPCM) { chan[c.chan].macroVolMul=(ins->type==DIV_INS_AMIGA)?64:127; chan[c.chan].isNewSegaPCM=(ins->type==DIV_INS_SEGAPCM); - chan[c.chan].pcm.sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].pcm.sample=ins->amiga.getSample(c.value); if (chan[c.chan].pcm.sample<0 || chan[c.chan].pcm.sample>=parent->song.sampleLen) { chan[c.chan].pcm.sample=-1; if (dumpWrites) { diff --git a/src/engine/platform/snes.cpp b/src/engine/platform/snes.cpp index 8752c08b..053ac9b7 100644 --- a/src/engine/platform/snes.cpp +++ b/src/engine/platform/snes.cpp @@ -336,7 +336,7 @@ int DivPlatformSNES::dispatch(DivCommand c) { } chan[c.chan].ws.init(ins,chan[c.chan].wtLen,15,chan[c.chan].insChanged); } else { - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); chan[c.chan].useWave=false; } if (chan[c.chan].useWave || chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) { diff --git a/src/engine/platform/sound/namco.cpp b/src/engine/platform/sound/namco.cpp index 811c34ab..473a80c6 100644 --- a/src/engine/platform/sound/namco.cpp +++ b/src/engine/platform/sound/namco.cpp @@ -754,9 +754,15 @@ void namco_audio_device::sound_stream_update(short** outputs, int len) int cnt; if (voice->noise_state) - buffer[i]+=noise_data; - else + { +buffer[i]+=noise_data; + voice->last_out=noise_data; +} + else { buffer[i]+=-noise_data; + voice->last_out=-noise_data; + +} if (hold) { diff --git a/src/engine/platform/swan.cpp b/src/engine/platform/swan.cpp index 64f7256f..f10a4e4e 100644 --- a/src/engine/platform/swan.cpp +++ b/src/engine/platform/swan.cpp @@ -234,7 +234,7 @@ int DivPlatformSwan::dispatch(DivCommand c) { dacPos=0; dacPeriod=0; if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) { - dacSample=ins->amiga.getSample(c.value); + 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); diff --git a/src/engine/platform/vera.cpp b/src/engine/platform/vera.cpp index f5951084..5021ac85 100644 --- a/src/engine/platform/vera.cpp +++ b/src/engine/platform/vera.cpp @@ -235,7 +235,7 @@ int DivPlatformVERA::dispatch(DivCommand c) { if (c.chan<16) { rWriteLo(c.chan,2,chan[c.chan].vol); } else { - chan[16].pcm.sample=parent->getIns(chan[16].ins,DIV_INS_VERA)->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[16].pcm.sample=parent->getIns(chan[16].ins,DIV_INS_VERA)->amiga.getSample(c.value); if (chan[16].pcm.sample<0 || chan[16].pcm.sample>=parent->song.sampleLen) { chan[16].pcm.sample=-1; } diff --git a/src/engine/platform/vrc6.cpp b/src/engine/platform/vrc6.cpp index e35f2393..bb1a7a42 100644 --- a/src/engine/platform/vrc6.cpp +++ b/src/engine/platform/vrc6.cpp @@ -242,7 +242,7 @@ int DivPlatformVRC6::dispatch(DivCommand c) { if (chan[c.chan].pcm) { if (skipRegisterWrites) break; if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) { - chan[c.chan].dacSample=ins->amiga.getSample(c.value); + 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) { chan[c.chan].dacSample=-1; if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0); diff --git a/src/engine/platform/x1_010.cpp b/src/engine/platform/x1_010.cpp index 8d564e32..093b952c 100644 --- a/src/engine/platform/x1_010.cpp +++ b/src/engine/platform/x1_010.cpp @@ -539,7 +539,7 @@ int DivPlatformX1_010::dispatch(DivCommand c) { if (chan[c.chan].furnacePCM) { chan[c.chan].pcm=true; chan[c.chan].macroInit(ins); - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); if (isBanked) { diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index 95ab537f..3419a1b6 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -449,7 +449,7 @@ void DivPlatformYM2203::tick(bool sysTick) { if (parent->song.linearPitch==2) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2,chipClock,CHIP_FREQBASE,11); } else { - int fNum=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2); + int fNum=parent->calcFreq(chan[i].baseFreq&0x7ff,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,4,chan[i].pitch2); int block=(chan[i].baseFreq&0xf800)>>11; if (fNum<0) fNum=0; if (fNum>2047) { diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index b5dba5f5..fc0b08de 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -796,7 +796,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].vol; immWrite(0x10b,chan[c.chan].outVol); } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(0x100,0x01); // reset diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 858886d8..261163e5 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -731,7 +731,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].vol; immWrite(0x1b,chan[c.chan].outVol); } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff); @@ -802,7 +802,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) { if (!chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff); diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index f53e239d..e1b856f9 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -798,7 +798,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { chan[c.chan].outVol=chan[c.chan].vol; immWrite(0x1b,chan[c.chan].outVol); } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff); @@ -869,7 +869,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { if (!chan[c.chan].std.vol.will) { chan[c.chan].outVol=chan[c.chan].vol; } - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (chan[c.chan].sample>=0 && chan[c.chan].samplesong.sampleLen) { DivSample* s=parent->getSample(chan[c.chan].sample); immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff); diff --git a/src/engine/platform/ymz280b.cpp b/src/engine/platform/ymz280b.cpp index 4301fcc8..7c7c5686 100644 --- a/src/engine/platform/ymz280b.cpp +++ b/src/engine/platform/ymz280b.cpp @@ -212,7 +212,7 @@ int DivPlatformYMZ280B::dispatch(DivCommand c) { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA); chan[c.chan].isNewYMZ=ins->type==DIV_INS_YMZ280B; chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:255; - chan[c.chan].sample=ins->amiga.getSample(c.value); + if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value); if (c.value!=DIV_NOTE_NULL) { chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); } diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 66d94447..e0f9e99a 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -1597,6 +1597,7 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi // logic starts here for (int i=0; i0) { disCont[i].flush(disCont[i].lastAvail); @@ -1696,6 +1697,10 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi totalProcessed=size-(runLeftG>>MASTER_CLOCK_PREC); for (int i=0; i", diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 1b89de31..e0844328 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -5156,6 +5156,7 @@ void FurnaceGUI::drawInsEdit() { if (ins->type==DIV_INS_ADPCMB) waveMax=0; if (ins->type==DIV_INS_QSOUND) waveMax=0; if (ins->type==DIV_INS_YMZ280B) waveMax=0; + if (ins->type==DIV_INS_RF5C68) waveMax=0; if (ins->type==DIV_INS_MSM5232) waveMax=0; if (ins->type==DIV_INS_MSM6258) waveMax=0; if (ins->type==DIV_INS_MSM6295) waveMax=0;