From ecfbee6f531931014fa2ffe4db98d61b798a3a5f Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Mon, 4 Aug 2025 17:31:38 -0700 Subject: [PATCH] libOpenMPT: Updated to version 0.8.2 Signed-off-by: Christopher Snowhill --- Frameworks/OpenMPT/OpenMPT/Makefile | 5 ++ Frameworks/OpenMPT/OpenMPT/build/dist.mk | 6 +- .../OpenMPT/build/make/config-defaults.mk | 7 ++ .../OpenMPT/build/svn_version/svn_version.h | 8 +- .../libopenmpt.xcodeproj/project.pbxproj | 2 + .../libopenmpt.xcodeproj/project.pbxproj | 2 + .../OpenMPT/OpenMPT/common/GzipWriter.h | 49 +++++++++++-- .../OpenMPT/common/serialization_utils.h | 2 +- .../OpenMPT/OpenMPT/common/versionNumber.h | 4 +- .../OpenMPT/libopenmpt/libopenmpt_version.h | 2 +- .../OpenMPT/libopenmpt/libopenmpt_version.mk | 4 +- .../OpenMPT/OpenMPT/openmpt123/openmpt123.cpp | 19 +++++ .../OpenMPT/openmpt123/openmpt123_flac.hpp | 4 +- .../OpenMPT/openmpt123/openmpt123_stdio.hpp | 2 +- Frameworks/OpenMPT/OpenMPT/sounddsp/EQ.cpp | 2 + .../OpenMPT/OpenMPT/sounddsp/Reverb.cpp | 7 +- .../OpenMPT/OpenMPT/soundlib/Fastmix.cpp | 72 +++++++++++------- .../OpenMPT/OpenMPT/soundlib/Load_fc.cpp | 19 ++++- .../OpenMPT/OpenMPT/soundlib/MIDIMacros.cpp | 4 +- .../OpenMPT/OpenMPT/soundlib/ModSequence.cpp | 8 +- .../OpenMPT/soundlib/SampleFormatFLAC.cpp | 6 +- .../OpenMPT/OpenMPT/soundlib/Snd_defs.h | 1 + .../OpenMPT/OpenMPT/soundlib/Snd_fx.cpp | 32 +++++--- .../OpenMPT/OpenMPT/soundlib/Sndfile.cpp | 1 + Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h | 3 +- .../OpenMPT/soundlib/UpgradeModule.cpp | 1 + .../OpenMPT/OpenMPT/soundlib/load_j2b.cpp | 73 ++++++++++++++----- .../OpenMPT/OpenMPT/src/mpt/arch/arch.hpp | 1 + .../OpenMPT/src/mpt/arch/feature_fence.hpp | 57 +++++++++++++++ .../OpenMPT/src/mpt/base/detect_quirks.hpp | 14 +++- .../OpenMPT/OpenMPT/src/mpt/crc/crc.hpp | 3 +- .../src/mpt/io_read/filedata_memory.hpp | 14 +++- .../OpenMPT/OpenMPT/src/mpt/mutex/mutex.hpp | 8 +- .../OpenMPT/OpenMPT/src/mpt/random/device.hpp | 1 + .../libOpenMPT.xcodeproj/project.pbxproj | 4 + 35 files changed, 348 insertions(+), 99 deletions(-) create mode 100644 Frameworks/OpenMPT/OpenMPT/src/mpt/arch/feature_fence.hpp diff --git a/Frameworks/OpenMPT/OpenMPT/Makefile b/Frameworks/OpenMPT/OpenMPT/Makefile index 3cc4a0cfc..75ab0664e 100644 --- a/Frameworks/OpenMPT/OpenMPT/Makefile +++ b/Frameworks/OpenMPT/OpenMPT/Makefile @@ -360,6 +360,9 @@ endif ifeq ($(UNAME_S),OpenBSD) HOST_FLAVOUR=OPENBSD endif +ifeq ($(UNAME_S),DragonFly) +HOST_FLAVOUR=DRAGONFLY +endif ifeq ($(UNAME_S),Haiku) HOST_FLAVOUR=HAIKU endif @@ -408,6 +411,8 @@ TAR_C=tar -c -N else TAR_C=tar -c -F pax -N endif +else ifeq ($(findstring DragonFly,$(UNAME_S)),DragonFly) +TAR_C=tar -c --format pax --numeric-owner --uname "" --gname "" --uid 0 --gid 0 else ifeq ($(findstring BSD,$(UNAME_S)),BSD) TAR_C=tar -c --format pax --numeric-owner --uname "" --gname "" --uid 0 --gid 0 else diff --git a/Frameworks/OpenMPT/OpenMPT/build/dist.mk b/Frameworks/OpenMPT/OpenMPT/build/dist.mk index b2a7e8453..e8b2503af 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/dist.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/dist.mk @@ -1,4 +1,4 @@ -MPT_SVNVERSION=23497 -MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.1 -MPT_SVNDATE=2025-06-14T13:04:39.042416Z +MPT_SVNVERSION=23826 +MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.2 +MPT_SVNDATE=2025-07-19T10:45:24.126020Z diff --git a/Frameworks/OpenMPT/OpenMPT/build/make/config-defaults.mk b/Frameworks/OpenMPT/OpenMPT/build/make/config-defaults.mk index 56771302b..ce46caf02 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/make/config-defaults.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/make/config-defaults.mk @@ -53,6 +53,13 @@ LDLIBS_PLATFORM=-lc++ -lc include build/make/config-clang.mk MPT_COMPILER_NOALLOCAH=1 +else ifeq ($(HOST_FLAVOUR),DRAGONFLY) + +NO_PORTAUDIOCPP?=1 +NO_PULSEAUDIO?=1 +include build/make/config-gcc.mk +MPT_COMPILER_NOALLOCAH=1 + else ifeq ($(HOST_FLAVOUR),HAIKU) NO_PULSEAUDIO?=1 diff --git a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h index 27f1cdd9c..f88b2e4f6 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h +++ b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h @@ -1,10 +1,10 @@ #pragma once -#define OPENMPT_VERSION_SVNVERSION "23497" -#define OPENMPT_VERSION_REVISION 23497 +#define OPENMPT_VERSION_SVNVERSION "23826" +#define OPENMPT_VERSION_REVISION 23826 #define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.1" -#define OPENMPT_VERSION_DATE "2025-06-14T13:04:39.042416Z" +#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.8.2" +#define OPENMPT_VERSION_DATE "2025-07-19T10:45:24.126020Z" #define OPENMPT_VERSION_IS_PACKAGE 1 diff --git a/Frameworks/OpenMPT/OpenMPT/build/xcode-ios/libopenmpt.xcodeproj/project.pbxproj b/Frameworks/OpenMPT/OpenMPT/build/xcode-ios/libopenmpt.xcodeproj/project.pbxproj index 020820abd..f541d2514 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/xcode-ios/libopenmpt.xcodeproj/project.pbxproj +++ b/Frameworks/OpenMPT/OpenMPT/build/xcode-ios/libopenmpt.xcodeproj/project.pbxproj @@ -364,6 +364,7 @@ 54F2D0191B80C78B8982EE59 /* algorithm.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = algorithm.hpp; path = ../../src/mpt/base/algorithm.hpp; sourceTree = ""; }; 55356226EAAC215859487866 /* span.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = span.hpp; path = ../../src/mpt/audio/span.hpp; sourceTree = ""; }; 55C6E46D9A1589DFDC3CC2AD /* Dlsbank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Dlsbank.cpp; path = ../../soundlib/Dlsbank.cpp; sourceTree = ""; }; + 55E9D1C649E91B38CED43006 /* feature_fence.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = feature_fence.hpp; path = ../../src/mpt/arch/feature_fence.hpp; sourceTree = ""; }; 55EF6B83EC187D75AD7ED9C3 /* tests_endian_int24.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = tests_endian_int24.hpp; path = ../../src/mpt/endian/tests/tests_endian_int24.hpp; sourceTree = ""; }; 5609DBF3C331EA65C4C4DA33 /* utility.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = utility.hpp; path = ../../src/mpt/base/utility.hpp; sourceTree = ""; }; 567D9E616834DE53DDA2CCA1 /* InstrumentExtensions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentExtensions.cpp; path = ../../soundlib/InstrumentExtensions.cpp; sourceTree = ""; }; @@ -1517,6 +1518,7 @@ isa = PBXGroup; children = ( 09573FAA7A79E09C30408DEA /* arch.hpp */, + 55E9D1C649E91B38CED43006 /* feature_fence.hpp */, 1197459E05968F108A81A3DE /* feature_flags.hpp */, 473316F00DC10E627BC33530 /* x86_amd64.hpp */, ); diff --git a/Frameworks/OpenMPT/OpenMPT/build/xcode-macosx/libopenmpt.xcodeproj/project.pbxproj b/Frameworks/OpenMPT/OpenMPT/build/xcode-macosx/libopenmpt.xcodeproj/project.pbxproj index 9e8a80f78..31a0936ae 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/xcode-macosx/libopenmpt.xcodeproj/project.pbxproj +++ b/Frameworks/OpenMPT/OpenMPT/build/xcode-macosx/libopenmpt.xcodeproj/project.pbxproj @@ -364,6 +364,7 @@ 54F2D0191B80C78B8982EE59 /* algorithm.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = algorithm.hpp; path = ../../src/mpt/base/algorithm.hpp; sourceTree = ""; }; 55356226EAAC215859487866 /* span.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = span.hpp; path = ../../src/mpt/audio/span.hpp; sourceTree = ""; }; 55C6E46D9A1589DFDC3CC2AD /* Dlsbank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Dlsbank.cpp; path = ../../soundlib/Dlsbank.cpp; sourceTree = ""; }; + 55E9D1C649E91B38CED43006 /* feature_fence.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = feature_fence.hpp; path = ../../src/mpt/arch/feature_fence.hpp; sourceTree = ""; }; 55EF6B83EC187D75AD7ED9C3 /* tests_endian_int24.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = tests_endian_int24.hpp; path = ../../src/mpt/endian/tests/tests_endian_int24.hpp; sourceTree = ""; }; 5609DBF3C331EA65C4C4DA33 /* utility.hpp */ = {isa = PBXFileReference; lastKnownFileType = text; name = utility.hpp; path = ../../src/mpt/base/utility.hpp; sourceTree = ""; }; 567D9E616834DE53DDA2CCA1 /* InstrumentExtensions.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = InstrumentExtensions.cpp; path = ../../soundlib/InstrumentExtensions.cpp; sourceTree = ""; }; @@ -1517,6 +1518,7 @@ isa = PBXGroup; children = ( 09573FAA7A79E09C30408DEA /* arch.hpp */, + 55E9D1C649E91B38CED43006 /* feature_fence.hpp */, 1197459E05968F108A81A3DE /* feature_flags.hpp */, 473316F00DC10E627BC33530 /* x86_amd64.hpp */, ); diff --git a/Frameworks/OpenMPT/OpenMPT/common/GzipWriter.h b/Frameworks/OpenMPT/OpenMPT/common/GzipWriter.h index ca3ade7de..dbf45bc65 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/GzipWriter.h +++ b/Frameworks/OpenMPT/OpenMPT/common/GzipWriter.h @@ -12,12 +12,15 @@ #include "openmpt/all/BuildSettings.hpp" -#include "mptString.h" #include "mpt/io/io.hpp" #include "mpt/io/io_stdstream.hpp" +#include "mptString.h" + #ifdef MPT_WITH_ZLIB +#include + #include OPENMPT_NAMESPACE_BEGIN @@ -25,15 +28,31 @@ OPENMPT_NAMESPACE_BEGIN inline void WriteGzip(std::ostream &output, std::string &outData, const mpt::ustring &fileName) { z_stream strm{}; + int zlib_errc = Z_OK; strm.avail_in = static_cast(outData.size()); strm.next_in = reinterpret_cast(outData.data()); - if(deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 | 16, 9, Z_DEFAULT_STRATEGY) != Z_OK) - throw std::runtime_error{"zlib init failed"}; + zlib_errc = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 | 16, 9, Z_DEFAULT_STRATEGY); + if(zlib_errc == Z_MEM_ERROR) + { + mpt::throw_out_of_memory(); + } else if(zlib_errc < Z_OK) + { + throw std::runtime_error{"zlib: deflateInit2() failed"}; + } gz_header gzHeader{}; - gzHeader.time = static_cast(time(nullptr)); + gzHeader.time = static_cast(std::time(nullptr)); std::string filenameISO = mpt::ToCharset(mpt::Charset::ISO8859_1, fileName); gzHeader.name = reinterpret_cast(filenameISO.data()); - deflateSetHeader(&strm, &gzHeader); + zlib_errc = deflateSetHeader(&strm, &gzHeader); + if(zlib_errc == Z_MEM_ERROR) + { + deflateEnd(&strm); + mpt::throw_out_of_memory(); + } else if(zlib_errc < Z_OK) + { + deflateEnd(&strm); + throw std::runtime_error{"zlib: deflateSetHeader() failed"}; + } try { do @@ -41,15 +60,33 @@ inline void WriteGzip(std::ostream &output, std::string &outData, const mpt::ust std::array buffer; strm.avail_out = static_cast(buffer.size()); strm.next_out = buffer.data(); - deflate(&strm, Z_FINISH); + zlib_errc = deflate(&strm, Z_FINISH); + if(zlib_errc == Z_BUF_ERROR) + { + // expected + } else if(zlib_errc == Z_MEM_ERROR) + { + mpt::throw_out_of_memory(); + } else if(zlib_errc < Z_OK) + { + throw std::runtime_error{"zlib: deflate() failed"}; + } mpt::IO::WritePartial(output, buffer, buffer.size() - strm.avail_out); } while(strm.avail_out == 0); + } catch(mpt::out_of_memory e) + { deflateEnd(&strm); + mpt::rethrow_out_of_memory(e); } catch(const std::exception &) + { + deflateEnd(&strm); + throw; + } catch(...) { deflateEnd(&strm); throw; } + deflateEnd(&strm); } OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/common/serialization_utils.h b/Frameworks/OpenMPT/OpenMPT/common/serialization_utils.h index 16b1d8216..5d154ad0c 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/serialization_utils.h +++ b/Frameworks/OpenMPT/OpenMPT/common/serialization_utils.h @@ -42,7 +42,7 @@ OPENMPT_NAMESPACE_BEGIN #ifdef SSB_LOGGING -#define SSB_LOG(x) MPT_LOG_GLOBAL(LogDebug, "serialization", x) +#define SSB_LOG(x) MPT_LOG_GLOBAL(LogDebug, "serialization", (x)) #else #define SSB_LOG(x) do { } while(0) #endif diff --git a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h index fcee664aa..2c085e58b 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h +++ b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h @@ -15,5 +15,5 @@ // Version definitions. The only thing that needs to be changed when changing version number. #define VER_MAJORMAJOR 1 #define VER_MAJOR 32 -#define VER_MINOR 01 -#define VER_MINORMINOR 04 +#define VER_MINOR 03 +#define VER_MINORMINOR 00 diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h index a6b1ca882..37882449d 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h @@ -21,7 +21,7 @@ /*! \brief libopenmpt minor version number */ #define OPENMPT_API_VERSION_MINOR 8 /*! \brief libopenmpt patch version number */ -#define OPENMPT_API_VERSION_PATCH 1 +#define OPENMPT_API_VERSION_PATCH 2 /*! \brief libopenmpt pre-release tag */ #define OPENMPT_API_VERSION_PREREL "" /*! \brief libopenmpt pre-release flag */ diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk index b3d6880b6..3873b202b 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.mk @@ -1,8 +1,8 @@ LIBOPENMPT_VERSION_MAJOR=0 LIBOPENMPT_VERSION_MINOR=8 -LIBOPENMPT_VERSION_PATCH=1 +LIBOPENMPT_VERSION_PATCH=2 LIBOPENMPT_VERSION_PREREL= LIBOPENMPT_LTVER_CURRENT=5 -LIBOPENMPT_LTVER_REVISION=1 +LIBOPENMPT_LTVER_REVISION=2 LIBOPENMPT_LTVER_AGE=5 diff --git a/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123.cpp b/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123.cpp index eacc8be72..89e4819e4 100644 --- a/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123.cpp +++ b/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123.cpp @@ -38,6 +38,25 @@ static const char * const license = #include "openmpt123_config.hpp" #include "mpt/base/detect_compiler.hpp" + +#if MPT_COMPILER_GCC + +#ifdef MPT_COMPILER_SETTING_QUIRK_GCC_BROKEN_IPA +// See . +#if MPT_GCC_BEFORE(9, 0, 0) +// Earlier GCC get confused about setting a global function attribute. +// We need to check for 9.0 instead of 9.1 because of +// . +// It also gets confused when setting global optimization -O1, +// so we have no way of fixing GCC 8 or earlier. +//#pragma GCC optimize("O1") +#else +#pragma GCC optimize("no-ipa-ra") +#endif +#endif // MPT_COMPILER_SETTING_QUIRK_GCC_BROKEN_IPA + +#endif // MPT_COMPILER_GCC + #include "mpt/base/detect_os.hpp" #include "mpt/base/detect_quirks.hpp" diff --git a/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_flac.hpp b/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_flac.hpp index 727be20a8..2f9ca5581 100644 --- a/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_flac.hpp +++ b/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_flac.hpp @@ -19,7 +19,7 @@ #include "mpt/base/saturate_round.hpp" #include -#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS) +#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD) #include #endif @@ -71,7 +71,7 @@ public: FLAC__stream_encoder_set_bits_per_sample( encoder, flags.use_float ? 24 : 16 ); FLAC__stream_encoder_set_sample_rate( encoder, flags.samplerate ); FLAC__stream_encoder_set_compression_level( encoder, 8 ); -#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS) +#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD) std::uint32_t threads = static_cast(std::max(std::thread::hardware_concurrency(), static_cast(1))); // Work-around . //FLAC__stream_encoder_set_num_threads( encoder, threads ); diff --git a/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_stdio.hpp b/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_stdio.hpp index 64b46fc7b..c54d0dba7 100644 --- a/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_stdio.hpp +++ b/Frameworks/OpenMPT/OpenMPT/openmpt123/openmpt123_stdio.hpp @@ -90,7 +90,7 @@ public: switch (new_mode) { case FILE_mode::text: fflush( file ); - #if defined(UNICODE) + #if defined(UNICODE) && MPT_LIBC_MS_AT_LEAST(MPT_LIBC_MS_VER_UCRT) old_mode = _setmode( _fileno( file ), _O_U8TEXT ); #else old_mode = _setmode( _fileno( file ), _O_TEXT ); diff --git a/Frameworks/OpenMPT/OpenMPT/sounddsp/EQ.cpp b/Frameworks/OpenMPT/OpenMPT/sounddsp/EQ.cpp index b58e23bc5..35dd403dd 100644 --- a/Frameworks/OpenMPT/OpenMPT/sounddsp/EQ.cpp +++ b/Frameworks/OpenMPT/OpenMPT/sounddsp/EQ.cpp @@ -102,6 +102,7 @@ void CEQ::ProcessTemplate(TMixSample *frontBuffer, TMixSample *rearBuffer, std:: unsigned int old_csr = 0; if(CPU::HasFeatureSet(CPU::feature::sse) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { + mpt::arch::feature_fence_aquire(); old_csr = _mm_getcsr(); _mm_setcsr((old_csr & ~(_MM_DENORMALS_ZERO_MASK | _MM_FLUSH_ZERO_MASK)) | _MM_DENORMALS_ZERO_ON | _MM_FLUSH_ZERO_ON); } @@ -124,6 +125,7 @@ void CEQ::ProcessTemplate(TMixSample *frontBuffer, TMixSample *rearBuffer, std:: if(CPU::HasFeatureSet(CPU::feature::sse) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { _mm_setcsr(old_csr); + mpt::arch::feature_fence_release(); } #endif } diff --git a/Frameworks/OpenMPT/OpenMPT/sounddsp/Reverb.cpp b/Frameworks/OpenMPT/OpenMPT/sounddsp/Reverb.cpp index e4ce2648b..f871b9b23 100644 --- a/Frameworks/OpenMPT/OpenMPT/sounddsp/Reverb.cpp +++ b/Frameworks/OpenMPT/OpenMPT/sounddsp/Reverb.cpp @@ -159,7 +159,7 @@ const REFLECTIONPRESET gReflectionsPreset[ENVIRONMENT_NUMREFLECTIONS] = // Implementation // -MPT_FORCEINLINE int32 ftol(float f) { return static_cast(f); } +static MPT_FORCEINLINE int32 ftol(float f) { return static_cast(f); } static void I3dl2_to_Generic( const SNDMIX_REVERB_PROPERTIES *pReverb, @@ -597,6 +597,7 @@ void CReverb::ReverbProcessPostFiltering1x(const int32 * MPT_RESTRICT pRvb, int3 #if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2) if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { + mpt::arch::feature_fence_guard arch_feature_guard; __m128i nDCRRvb_Y1 = Load64SSE(gnDCRRvb_Y1); __m128i nDCRRvb_X1 = Load64SSE(gnDCRRvb_X1); __m128i in = _mm_set1_epi32(0); @@ -659,6 +660,7 @@ void CReverb::ReverbDCRemoval(int32 * MPT_RESTRICT pBuffer, uint32 nSamples) #if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2) if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { + mpt::arch::feature_fence_guard arch_feature_guard; __m128i nDCRRvb_Y1 = Load64SSE(gnDCRRvb_Y1); __m128i nDCRRvb_X1 = Load64SSE(gnDCRRvb_X1); while(nSamples--) @@ -724,6 +726,7 @@ void CReverb::ProcessPreDelay(SWRvbRefDelay * MPT_RESTRICT pPreDelay, const int3 #if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2) if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { + mpt::arch::feature_fence_guard arch_feature_guard; __m128i coeffs = _mm_cvtsi32_si128(pPreDelay->nCoeffs.lr); __m128i history = _mm_cvtsi32_si128(pPreDelay->History.lr); __m128i preDifCoeffs = _mm_cvtsi32_si128(pPreDelay->nPreDifCoeffs.lr); @@ -796,6 +799,7 @@ void CReverb::ProcessReflections(SWRvbRefDelay * MPT_RESTRICT pPreDelay, LR16 * #if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2) if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { + mpt::arch::feature_fence_guard arch_feature_guard; union { __m128i xmm; @@ -891,6 +895,7 @@ void CReverb::ProcessLateReverb(SWLateReverb * MPT_RESTRICT pReverb, LR16 * MPT_ #if defined(MPT_WANT_ARCH_INTRINSICS_X86_SSE2) && defined(MPT_ARCH_INTRINSICS_X86_SSE2) if(CPU::HasFeatureSet(CPU::feature::sse2) && CPU::HasModesEnabled(CPU::mode::xmm128sse)) { + mpt::arch::feature_fence_guard arch_feature_guard; int delayPos = pReverb->nDelayPos & RVBDLY_MASK; __m128i rvbOutGains = Load64SSE(pReverb->RvbOutGains); __m128i difCoeffs = Load64SSE(pReverb->nDifCoeffs); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp index bfce6adc7..6b4556ae9 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Fastmix.cpp @@ -97,7 +97,7 @@ struct MixLoopState // Check how many samples can be rendered without encountering loop or sample end, and also update loop position / direction MPT_FORCEINLINE uint32 GetSampleCount(ModChannel &chn, uint32 nSamples) const { - int32 nLoopStart = chn.dwFlags[CHN_LOOP] ? chn.nLoopStart : 0; + const int32 nLoopStart = chn.dwFlags[CHN_LOOP] ? chn.nLoopStart : 0; SamplePosition nInc = chn.increment; if(nSamples <= 0 || nInc.IsZero() || !chn.nLength || !samplePointer) @@ -227,35 +227,24 @@ struct MixLoopState { if(nPosInt >= lookaheadStart) { -#if 0 - const uint32 oldCount = nSmpCount; - - // When going backwards - we can only go back up to lookaheadStart. - // When going forwards - read through the whole pre-computed wrap-around buffer if possible. - // TODO: ProTracker sample swapping needs hard cut at sample end. - int32 samplesToRead = nInc.IsNegative() - ? (nPosInt - lookaheadStart) - //: 2 * InterpolationMaxLookahead - (nPosInt - mixLoopState.lookaheadStart); - : (chn.nLoopEnd - nPosInt); - //LimitMax(samplesToRead, chn.nLoopEnd - chn.nLoopStart); - nSmpCount = SamplesToBufferLength(samplesToRead, chn); - Limit(nSmpCount, 1u, oldCount); -#else - if (nInc.IsNegative()) + if(nInc.IsNegative()) { nSmpCount = DistanceToBufferLength(SamplePosition(lookaheadStart, 0), nPos, nInv); - } else + chn.pCurrentSample = lookaheadPointer; + } else if(nPosInt <= chn.nLoopEnd) { nSmpCount = DistanceToBufferLength(nPos, SamplePosition(chn.nLoopEnd, 0), nInv); + chn.pCurrentSample = lookaheadPointer; + } else + { + nSmpCount = DistanceToBufferLength(nPos, SamplePosition(chn.nLength, 0), nInv); } -#endif - chn.pCurrentSample = lookaheadPointer; checkDest = false; } else if(chn.dwFlags[CHN_WRAPPED_LOOP] && isAtLoopStart) { // We just restarted the loop, so interpolate correctly after wrapping around nSmpCount = DistanceToBufferLength(nPos, SamplePosition(nLoopStart + InterpolationLookaheadBufferSize, 0), nInv); - chn.pCurrentSample = lookaheadPointer + (chn.nLoopEnd - nLoopStart) * chn.pModSample->GetBytesPerSample(); + chn.pCurrentSample = lookaheadPointer + (chn.nLength - nLoopStart) * chn.pModSample->GetBytesPerSample(); checkDest = false; } else if(nInc.IsPositive() && static_cast(nPosDest) >= lookaheadStart && nSmpCount > 1) { @@ -325,12 +314,45 @@ void CSoundFile::CreateStereoMix(int count) } +std::pair CSoundFile::GetChannelOffsets(const ModChannel &chn, CHANNELINDEX channel) +{ + mixsample_t *pOfsR = &m_dryROfsVol; + mixsample_t *pOfsL = &m_dryLOfsVol; +#ifndef NO_REVERB + if(((m_MixerSettings.DSPMask & SNDDSP_REVERB) && !chn.dwFlags[CHN_NOREVERB]) || chn.dwFlags[CHN_REVERB]) + { + pOfsR = &m_RvbROfsVol; + pOfsL = &m_RvbLOfsVol; + } +#endif + if(chn.dwFlags[CHN_SURROUND] && m_MixerSettings.gnChannels > 2) + { + pOfsR = &m_surroundROfsVol; + pOfsL = &m_surroundLOfsVol; + } + // Look for plugins associated with this implicit tracker channel. +#ifndef NO_PLUGINS + const PLUGINDEX mixPlugin = GetBestPlugin(chn, channel, PrioritiseInstrument, RespectMutes); + if((mixPlugin > 0) && (mixPlugin <= MAX_MIXPLUGINS) && m_MixPlugins[mixPlugin - 1].pMixPlugin != nullptr) + { + // Render into plugin buffer instead of global buffer + SNDMIXPLUGINSTATE &mixState = m_MixPlugins[mixPlugin - 1].pMixPlugin->m_MixState; + if(mixState.pMixBuffer) + { + pOfsR = &mixState.nVolDecayR; + pOfsL = &mixState.nVolDecayL; + } + } +#endif // NO_PLUGINS + return std::make_pair(pOfsL, pOfsR); +} + + bool CSoundFile::MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bool doMix) { if(chn.pCurrentSample || chn.nLOfs || chn.nROfs) { - mixsample_t *pOfsR = &m_dryROfsVol; - mixsample_t *pOfsL = &m_dryLOfsVol; + auto [pOfsL, pOfsR] = GetChannelOffsets(chn, channel); uint32 functionNdx = MixFuncTable::ResamplingModeToMixFlags(static_cast(chn.resamplingMode)); if(chn.dwFlags[CHN_16BIT]) functionNdx |= MixFuncTable::ndx16Bit; @@ -345,15 +367,11 @@ bool CSoundFile::MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bo { m_Reverb.TouchReverbSendBuffer(ReverbSendBuffer, m_RvbROfsVol, m_RvbLOfsVol, count); pbuffer = ReverbSendBuffer; - pOfsR = &m_RvbROfsVol; - pOfsL = &m_RvbLOfsVol; } #endif if(chn.dwFlags[CHN_SURROUND] && m_MixerSettings.gnChannels > 2) { pbuffer = MixRearBuffer; - pOfsR = &m_surroundROfsVol; - pOfsL = &m_surroundLOfsVol; } // Look for plugins associated with this implicit tracker channel. @@ -366,8 +384,6 @@ bool CSoundFile::MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bo if (mixState.pMixBuffer) { pbuffer = mixState.pMixBuffer; - pOfsR = &mixState.nVolDecayR; - pOfsL = &mixState.nVolDecayL; if (!(mixState.dwFlags & SNDMIXPLUGINSTATE::psfMixReady)) { StereoFill(pbuffer, count, *pOfsR, *pOfsL); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_fc.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_fc.cpp index 6203f96f5..6c5a7a0fe 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_fc.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_fc.cpp @@ -83,8 +83,9 @@ struct FCFileHeader return false; static constexpr uint32 MAX_FC_SIZE = 0x8'0000; // According to manual: Sample memory allocated = 100,000 bytes - if(sequenceSize % sizeof(FCPlaylistEntry) > 1 // Some files have a mysterious extra byte - || sequenceSize < sizeof(FCPlaylistEntry) || sequenceSize > 256 * 13 + const uint32 seqSize = SequenceSize(); + if(seqSize % sizeof(FCPlaylistEntry) > 1 // Some files have a mysterious extra byte + || seqSize < sizeof(FCPlaylistEntry) || seqSize > 256 * 13 || patternsSize % 64u || !patternsSize || patternsSize > 64 * 256 || patternsOffset > MAX_FC_SIZE || freqSequenceSize % 64u || !freqSequenceSize || freqSequenceSize > 64 * 256 || freqSequenceOffset > MAX_FC_SIZE || volSequenceSize % 64u || !volSequenceSize || volSequenceSize > 64 * 256 || volSequenceOffset > MAX_FC_SIZE @@ -102,12 +103,22 @@ struct FCFileHeader ORDERINDEX NumOrders() const { - return static_cast(sequenceSize / sizeof(FCPlaylistEntry)); + return static_cast(SequenceSize() / sizeof(FCPlaylistEntry)); } uint32 GetHeaderMinimumAdditionalSize() const { - return sequenceSize + (IsFC14() ? 80 : 0); + return SequenceSize() + (IsFC14() ? 80 : 0); + } + + uint32 SequenceSize() const + { + // A broken copy of cult.smod has a sequence size of 0 but the sequence data is actually in the place where it's supposed to be + if(sequenceSize > 0) + return sequenceSize; + if(const uint32 headerSize = IsFC14() ? 180 : 100; patternsOffset > headerSize) + return patternsOffset - headerSize; + return 0; } }; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/MIDIMacros.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/MIDIMacros.cpp index fd20760d7..73e92f91e 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/MIDIMacros.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/MIDIMacros.cpp @@ -357,8 +357,8 @@ std::string MIDIMacroConfig::Macro::NormalizedString() const { std::string sanitizedMacro = *this; - std::string::size_type pos; - while((pos = sanitizedMacro.find_first_not_of("0123456789ABCDEFabchmnopsuvxyz")) != std::string::npos) + std::string::size_type pos = 0; + while((pos = sanitizedMacro.find_first_not_of("0123456789ABCDEFabchmnopsuvxyz", pos)) != std::string::npos) { sanitizedMacro.erase(pos, 1); } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ModSequence.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ModSequence.cpp index 8bf26e837..8701e7e97 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ModSequence.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ModSequence.cpp @@ -21,7 +21,7 @@ OPENMPT_NAMESPACE_BEGIN ModSequence::ModSequence(CSoundFile &sndFile) - : m_sndFile(sndFile) + : m_sndFile{sndFile} { } @@ -33,6 +33,8 @@ ModSequence& ModSequence::operator=(const ModSequence &other) std::vector::assign(other.begin(), other.end()); m_name = other.m_name; m_restartPos = other.m_restartPos; + m_defaultTempo = other.m_defaultTempo; + m_defaultSpeed = other.m_defaultSpeed; return *this; } @@ -41,7 +43,9 @@ bool ModSequence::operator== (const ModSequence &other) const noexcept { return static_cast &>(*this) == other && m_name == other.m_name - && m_restartPos == other.m_restartPos; + && m_restartPos == other.m_restartPos + && m_defaultTempo == other.m_defaultTempo + && m_defaultSpeed == other.m_defaultSpeed; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatFLAC.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatFLAC.cpp index afb526c16..18b060b6e 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatFLAC.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/SampleFormatFLAC.cpp @@ -35,9 +35,11 @@ //#include "mpt/crc/crc.hpp" #include "OggStream.h" #include -#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS) +#ifdef MPT_WITH_FLAC +#if MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD) #include #endif +#endif #ifdef MPT_WITH_OGG #if MPT_COMPILER_CLANG #pragma clang diagnostic push @@ -698,7 +700,7 @@ bool CSoundFile::SaveFLACSample(SAMPLEINDEX nSample, std::ostream &f) const FLAC__stream_encoder_set_metadata(encoder, metadata.data(), numBlocks); #ifdef MODPLUG_TRACKER FLAC__stream_encoder_set_compression_level(encoder, TrackerSettings::Instance().m_FLACCompressionLevel); -#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_COMPILER_QUIRK_NO_STDCPP_THREADS) +#if (FLAC_API_VERSION_CURRENT >= 14) && MPT_PLATFORM_MULTITHREADED && !defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD) uint32 threads = TrackerSettings::Instance().m_FLACMultithreading ? static_cast(std::max(std::thread::hardware_concurrency(), static_cast(1))) : static_cast(1); // Work-around . //FLAC__stream_encoder_set_num_threads(encoder, threads); diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h index 0681f7013..78f1b367a 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_defs.h @@ -618,6 +618,7 @@ enum PlayBehaviour kITCarryAfterNoteOff, // Envelope Carry continues to function as normal even after note-off kFT2OffsetMemoryRequiresNote, // Offset memory is only updated when offset command is next to a note kITNoteCutWithPorta, // Note Cut (SCx) resets note frequency and interacts with tone portamento with row delay + kITVolColNoSlidePropagation, // Don't propagate volume command c/d parameter to regular command D memory // Add new play behaviours here. diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp index 3088a77b9..725b77819 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp @@ -1312,7 +1312,9 @@ std::vector CSoundFile::GetLength(enmGetLengthResetMode adjustMod for(uint32 i = 0; i < numTicks; i++) { chn.isFirstTick = (i == 0); - VolumeSlide(chn, vol); + // IT Compatibility: Volume column volume slides must not propagate their memory to the regular effect column + // Test case: VolColNoSlideMemoryPropagation.it + VolumeSlide(chn, vol, m_playBehaviour[kITVolColNoSlidePropagation]); } } break; @@ -3077,6 +3079,8 @@ bool CSoundFile::ProcessEffects() // Instrument Change ? if(instr) { + auto [oldChnOfsL, oldChnOfsR] = GetChannelOffsets(chn, nChn); + const ModSample *oldSample = chn.pModSample; //const ModInstrument *oldInstrument = chn.pModInstrument; @@ -3101,8 +3105,8 @@ bool CSoundFile::ProcessEffects() // When swapping samples without explicit note change (e.g. during portamento), avoid clicks at end of sample (as there won't be an NNA channel to fade the sample out) if(oldSample != nullptr && oldSample != chn.pModSample) { - m_dryLOfsVol += chn.nLOfs; - m_dryROfsVol += chn.nROfs; + *oldChnOfsL += chn.nLOfs; + *oldChnOfsR += chn.nROfs; chn.nLOfs = 0; chn.nROfs = 0; } @@ -3296,7 +3300,9 @@ bool CSoundFile::ProcessEffects() { chn.nOldVolParam = vol; } - VolumeSlide(chn, static_cast(volcmd == VOLCMD_VOLSLIDEUP ? (vol << 4) : vol)); + // IT Compatibility: Volume column volume slides must not propagate their memory to the regular effect column + // Test case: VolColNoSlideMemoryPropagation.it + VolumeSlide(chn, static_cast(volcmd == VOLCMD_VOLSLIDEUP ? (vol << 4) : vol), m_playBehaviour[kITVolColNoSlidePropagation]); break; case VOLCMD_FINEVOLUP: @@ -4833,12 +4839,15 @@ void CSoundFile::VolumeDownETX(const PlayState &playState, ModChannel &chn, ModC } -void CSoundFile::VolumeSlide(ModChannel &chn, ModCommand::PARAM param) const +void CSoundFile::VolumeSlide(ModChannel &chn, ModCommand::PARAM param, bool volCol) const { - if (param) - chn.nOldVolumeSlide = param; - else - param = chn.nOldVolumeSlide; + if(!volCol) + { + if(param) + chn.nOldVolumeSlide = param; + else + param = chn.nOldVolumeSlide; + } if((GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_DIGI | MOD_TYPE_STP | MOD_TYPE_DTM))) { @@ -5689,6 +5698,8 @@ void CSoundFile::ProcessSampleOffset(ModChannel &chn, CHANNELINDEX nChn, const P void CSoundFile::SampleOffset(ModChannel &chn, SmpLength param) const { + LimitMax(param, MAX_SAMPLE_LENGTH); + // ST3 compatibility: Instrument-less note recalls previous note's offset // Test case: OxxMemory.s3m if(m_playBehaviour[kST3OffsetWithoutInstrument] || GetType() == MOD_TYPE_MED) @@ -6285,6 +6296,9 @@ void CSoundFile::SetTempo(PlayState &playState, TEMPO param, bool setFromUI) con } else if(param < minTempo && !playState.m_flags[SONG_FIRSTTICK]) { // Tempo Slide + // Very old MPT versions (last confirmed version: 1.09.066) add/subtract the param only on the first tick. + // Newer MPT versions (first confirmed version: 1.09.090), add/subtract the param multiplied by 2 only on the first tick. + // In SVN r26, the behaviour was adjusted to match Impulse Tracker. This change is part of OpenMPT 1.17 RC1 but not the MPT Wild pre-beta. TEMPO tempDiff(param.GetInt() & 0x0F, 0); if((param.GetInt() & 0xF0) == 0x10) playState.m_nMusicTempo += tempDiff; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp index 3a4d26b87..e503ade94 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.cpp @@ -1228,6 +1228,7 @@ PlayBehaviourSet CSoundFile::GetSupportedPlaybackBehaviour(MODTYPE type) playBehaviour.set(kITDoublePortamentoSlides); playBehaviour.set(kITCarryAfterNoteOff); playBehaviour.set(kITNoteCutWithPorta); + playBehaviour.set(kITVolColNoSlidePropagation); break; case MOD_TYPE_XM: diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h index c1cc28ab6..f818dc67b 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h @@ -989,6 +989,7 @@ public: private: void CreateStereoMix(int count); bool MixChannel(int count, ModChannel &chn, CHANNELINDEX channel, bool doMix); + std::pair GetChannelOffsets(const ModChannel &chn, CHANNELINDEX channel); public: bool FadeSong(uint32 msec); private: @@ -1109,7 +1110,7 @@ protected: void FineVibrato(ModChannel &chn, uint32 param) const; void AutoVolumeSlide(ModChannel &chn, ModCommand::PARAM param) const; void VolumeDownETX(const PlayState &playState, ModChannel &chn, ModCommand::PARAM param) const; - void VolumeSlide(ModChannel &chn, ModCommand::PARAM param) const; + void VolumeSlide(ModChannel &chn, ModCommand::PARAM param, bool volCol = false) const; void PanningSlide(ModChannel &chn, ModCommand::PARAM param, bool memory = true) const; void ChannelVolSlide(ModChannel &chn, ModCommand::PARAM param) const; void ChannelVolumeDownWithDuration(ModChannel &chn, uint16 param = uint16_max) const; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp index 08ce11400..d0e3352db 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/UpgradeModule.cpp @@ -604,6 +604,7 @@ void CSoundFile::UpgradeModule() { kITDoublePortamentoSlides, MPT_V("1.32.00.27") }, { kITCarryAfterNoteOff, MPT_V("1.32.00.40") }, { kITNoteCutWithPorta, MPT_V("1.32.01.02") }, + { kITVolColNoSlidePropagation, MPT_V("1.32.02.03") }, }; for(const auto &b : behaviours) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/load_j2b.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/load_j2b.cpp index 22a2222b2..956001697 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/load_j2b.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/load_j2b.cpp @@ -1017,33 +1017,68 @@ bool CSoundFile::ReadJ2B(FileReader &file, ModLoadingFlags loadFlags) // Header is valid, now unpack the RIFF AM file using inflate z_stream strm{}; - if(inflateInit(&strm) != Z_OK) + int zlib_errc = Z_OK; + zlib_errc = inflateInit(&strm); + if(zlib_errc == Z_MEM_ERROR) + { + mpt::throw_out_of_memory(); + } else if(zlib_errc < Z_OK) + { return false; + } uint32 remainRead = fileHeader.packedLength, remainWrite = fileHeader.unpackedLength, totalWritten = 0; uint32 crc = 0; - std::vector amFileData(remainWrite); + std::vector amFileData; int retVal = Z_OK; - while(remainRead && remainWrite && retVal != Z_STREAM_END) + try { - Bytef buffer[mpt::IO::BUFFERSIZE_TINY]; - uint32 readSize = std::min(static_cast(sizeof(buffer)), remainRead); - file.ReadRaw(mpt::span(buffer, readSize)); - crc = static_cast(crc32(crc, buffer, readSize)); - - strm.avail_in = readSize; - strm.next_in = buffer; - do + amFileData.resize(remainWrite); + while(remainRead && remainWrite && retVal != Z_STREAM_END) { - strm.avail_out = remainWrite; - strm.next_out = amFileData.data() + totalWritten; - retVal = inflate(&strm, Z_NO_FLUSH); - uint32 written = remainWrite - strm.avail_out; - totalWritten += written; - remainWrite -= written; - } while(remainWrite && strm.avail_out == 0); + Bytef buffer[mpt::IO::BUFFERSIZE_TINY]; + uint32 readSize = std::min(static_cast(sizeof(buffer)), remainRead); + file.ReadRaw(mpt::span(buffer, readSize)); + crc = static_cast(crc32(crc, buffer, readSize)); - remainRead -= readSize; + strm.avail_in = readSize; + strm.next_in = buffer; + do + { + strm.avail_out = remainWrite; + strm.next_out = amFileData.data() + totalWritten; + zlib_errc = inflate(&strm, Z_NO_FLUSH); + if(zlib_errc == Z_BUF_ERROR) + { + // expected + } else if(zlib_errc == Z_MEM_ERROR) + { + mpt::throw_out_of_memory(); + } else if(zlib_errc < Z_OK) + { + inflateEnd(&strm); + return false; + } + retVal = zlib_errc; + uint32 written = remainWrite - strm.avail_out; + totalWritten += written; + remainWrite -= written; + } while(remainWrite && strm.avail_out == 0); + + remainRead -= readSize; + } + } catch(mpt::out_of_memory e) + { + inflateEnd(&strm); + mpt::rethrow_out_of_memory(e); + } catch(const std::exception &) + { + inflateEnd(&strm); + return false; + } catch(...) + { + inflateEnd(&strm); + return false; } inflateEnd(&strm); diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/arch.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/arch.hpp index 99c4b5758..9b89673d5 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/arch.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/arch.hpp @@ -4,6 +4,7 @@ #define MPT_ARCH_ARCH_HPP +#include "mpt/arch/feature_fence.hpp" #include "mpt/arch/feature_flags.hpp" #include "mpt/arch/x86_amd64.hpp" #include "mpt/base/detect.hpp" diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/feature_fence.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/feature_fence.hpp new file mode 100644 index 000000000..e54364700 --- /dev/null +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/arch/feature_fence.hpp @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */ + +#ifndef MPT_ARCH_FEATURE_FENCE_HPP +#define MPT_ARCH_FEATURE_FENCE_HPP + + +#include "mpt/base/detect.hpp" +#include "mpt/base/macros.hpp" +#include "mpt/base/namespace.hpp" + +#include + + + +namespace mpt { +inline namespace MPT_INLINE_NS { + + + +namespace arch { + + + +MPT_FORCEINLINE void feature_fence_aquire() noexcept { + std::atomic_signal_fence(std::memory_order_acquire); +} + +MPT_FORCEINLINE void feature_fence_release() noexcept { + std::atomic_signal_fence(std::memory_order_release); +} + +class feature_fence_guard { +public: + MPT_FORCEINLINE feature_fence_guard() noexcept { + mpt::arch::feature_fence_aquire(); + } + MPT_FORCEINLINE ~feature_fence_guard() noexcept { + mpt::arch::feature_fence_release(); + } + feature_fence_guard(feature_fence_guard &&) = delete; + feature_fence_guard(const feature_fence_guard &) = delete; + feature_fence_guard & operator=(feature_fence_guard &&) = delete; + feature_fence_guard & operator=(const feature_fence_guard &) = delete; +}; + + + +} // namespace arch + + + +} // namespace MPT_INLINE_NS +} // namespace mpt + + + +#endif // MPT_ARCH_FEATURE_FENCE_HPP diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_quirks.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_quirks.hpp index a4d0bc9a5..b7d25a458 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_quirks.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/base/detect_quirks.hpp @@ -103,9 +103,17 @@ +#if !MPT_PLATFORM_MULTITHREADED +#define MPT_LIBCXX_QUIRK_NO_STD_THREAD +#elif !MPT_COMPILER_GENERIC && MPT_OS_WINDOWS && MPT_LIBCXX_GNU && !defined(_GLIBCXX_HAS_GTHREADS) +#define MPT_LIBCXX_QUIRK_NO_STD_THREAD +#endif + + + #if MPT_OS_WINDOWS && MPT_COMPILER_MSVC #if MPT_WINNT_AT_LEAST(MPT_WIN_VISTA) -#define MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX +#define MPT_LIBCXX_QUIRK_COMPLEX_STD_MUTEX #endif #endif @@ -348,6 +356,10 @@ #if MPT_LIBCXX_GNU_BEFORE(13) #define MPT_LIBCXX_QUIRK_CHRONO_DATE_NO_ZONED_TIME #endif +#if MPT_LIBCXX_LLVM +// See +#define MPT_LIBCXX_QUIRK_CHRONO_DATE_NO_ZONED_TIME +#endif #if MPT_MSVC_AT_LEAST(2022, 6) && MPT_MSVC_BEFORE(2022, 7) // std::chrono triggers ICE in VS2022 17.6.0, see . #define MPT_LIBCXX_QUIRK_CHRONO_DATE_BROKEN_ZONED_TIME diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/crc/crc.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/crc/crc.hpp index 5d6e851f2..7f76db168 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/crc/crc.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/crc/crc.hpp @@ -7,10 +7,9 @@ #include "mpt/base/array.hpp" #include "mpt/base/detect.hpp" -#include "mpt/base/namespace.hpp" - #include "mpt/base/integer.hpp" #include "mpt/base/memory.hpp" +#include "mpt/base/namespace.hpp" #include diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/io_read/filedata_memory.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/io_read/filedata_memory.hpp index cbf8fe170..0619c4a90 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/io_read/filedata_memory.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/io_read/filedata_memory.hpp @@ -5,6 +5,7 @@ +#include "mpt/base/detect.hpp" #include "mpt/base/memory.hpp" #include "mpt/base/namespace.hpp" #include "mpt/io_read/filedata.hpp" @@ -12,6 +13,9 @@ #include #include +#if MPT_GCC_AT_LEAST(12, 0, 0) +#include +#endif @@ -65,7 +69,15 @@ public: return dst.first(0); } pos_type avail = std::min(streamLength - pos, static_cast(dst.size())); - std::copy(streamData + pos, streamData + static_cast(pos + avail), dst.data()); + const std::byte * src = streamData + pos; +#if MPT_GCC_AT_LEAST(12, 0, 0) + // work-around bogus -Warray-bounds + // work-around bogus -Wstringop-overflow + // See . + std::memcpy(dst.data(), src, avail); +#else + std::copy(src, src + avail, dst.data()); +#endif return dst.first(static_cast(avail)); } diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/mutex/mutex.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/mutex/mutex.hpp index 856af4e4b..8208fdeaa 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/mutex/mutex.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/mutex/mutex.hpp @@ -11,9 +11,7 @@ #if !MPT_PLATFORM_MULTITHREADED #define MPT_MUTEX_NONE 1 -#elif MPT_COMPILER_GENERIC -#define MPT_MUTEX_STD 1 -#elif MPT_OS_WINDOWS && MPT_LIBCXX_GNU && !defined(_GLIBCXX_HAS_GTHREADS) +#elif defined(MPT_LIBCXX_QUIRK_NO_STD_THREAD) #define MPT_MUTEX_WIN32 1 #else #define MPT_MUTEX_STD 1 @@ -31,7 +29,7 @@ #if MPT_MUTEX_STD #include -#ifdef MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX +#ifdef MPT_LIBCXX_QUIRK_COMPLEX_STD_MUTEX #include #include #endif @@ -48,7 +46,7 @@ inline namespace MPT_INLINE_NS { #if MPT_MUTEX_STD -#ifdef MPT_COMPILER_QUIRK_COMPLEX_STD_MUTEX +#ifdef MPT_LIBCXX_QUIRK_COMPLEX_STD_MUTEX using mutex = std::conditional::type; #else using mutex = std::mutex; diff --git a/Frameworks/OpenMPT/OpenMPT/src/mpt/random/device.hpp b/Frameworks/OpenMPT/OpenMPT/src/mpt/random/device.hpp index bea922a3e..a0ac41db4 100644 --- a/Frameworks/OpenMPT/OpenMPT/src/mpt/random/device.hpp +++ b/Frameworks/OpenMPT/OpenMPT/src/mpt/random/device.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include diff --git a/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj b/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj index a01955e30..5f7731047 100644 --- a/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj +++ b/Frameworks/OpenMPT/libOpenMPT.xcodeproj/project.pbxproj @@ -256,6 +256,7 @@ 83BB83FD2DF2BE22002077FC /* wav.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BB83F72DF2BE22002077FC /* wav.hpp */; }; 83BB83FE2DF2BE22002077FC /* wav_write.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BB83F92DF2BE22002077FC /* wav_write.hpp */; }; 83BB83FF2DF2BE22002077FC /* tags.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BB83F62DF2BE22002077FC /* tags.hpp */; }; + 83BDCD912E418723003FC007 /* feature_fence.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCD902E418723003FC007 /* feature_fence.hpp */; }; 83E5EFD01FFEF9D200659F0F /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E5EFCE1FFEF9D200659F0F /* config.h */; }; 83E5FC661FFEFA0D00659F0F /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E5FC2D1FFEFA0D00659F0F /* version.h */; }; 83E5FC681FFEFA0D00659F0F /* stdafx.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E5FC2F1FFEFA0D00659F0F /* stdafx.h */; }; @@ -734,6 +735,7 @@ 83BB83F72DF2BE22002077FC /* wav.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wav.hpp; sourceTree = ""; }; 83BB83F92DF2BE22002077FC /* wav_write.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = wav_write.hpp; sourceTree = ""; }; 83BB83FA2DF2BE22002077FC /* wav_write.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wav_write.cpp; sourceTree = ""; }; + 83BDCD902E418723003FC007 /* feature_fence.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = feature_fence.hpp; sourceTree = ""; }; 83E5EFBD1FFEF7CC00659F0F /* libOpenMPT.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = libOpenMPT.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 83E5EFCE1FFEF9D200659F0F /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = SOURCE_ROOT; }; 83E5EFCF1FFEF9D200659F0F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = SOURCE_ROOT; }; @@ -1487,6 +1489,7 @@ isa = PBXGroup; children = ( 83649BA62A03418500CD0580 /* arch.hpp */, + 83BDCD902E418723003FC007 /* feature_fence.hpp */, 83649BA52A03418500CD0580 /* feature_flags.hpp */, 83649BA72A03418500CD0580 /* x86_amd64.hpp */, ); @@ -2113,6 +2116,7 @@ 83E5FCDB1FFEFA1A00659F0F /* libopenmpt_stream_callbacks_file.h in Headers */, 830996BA27787E9A00857684 /* base.hpp in Headers */, 83E5FDC31FFEFA8500659F0F /* MIDIEvents.h in Headers */, + 83BDCD912E418723003FC007 /* feature_fence.hpp in Headers */, 83E5FDF81FFEFA8500659F0F /* Compressor.h in Headers */, 8309970C27787E9A00857684 /* detect_compiler.hpp in Headers */, 830996C227787E9A00857684 /* simple_integer.hpp in Headers */,