diff --git a/Frameworks/OpenMPT/OpenMPT/Makefile b/Frameworks/OpenMPT/OpenMPT/Makefile index 6069830b4..54d039d50 100644 --- a/Frameworks/OpenMPT/OpenMPT/Makefile +++ b/Frameworks/OpenMPT/OpenMPT/Makefile @@ -1253,6 +1253,7 @@ bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION).msvc.zip: bin/dist.mk bin/svn svn export ./build/premake/def bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/premake/def --native-eol CRLF svn export ./build/premake/inc bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/premake/inc --native-eol CRLF svn export ./build/premake/lnk bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/premake/lnk --native-eol CRLF + svn export ./build/scriptlib bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/scriptlib --native-eol CRLF svn export ./build/svn_version bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/svn_version --native-eol CRLF svn export ./build/vcpkg bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vcpkg --native-eol CRLF svn export ./build/vs bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs --native-eol CRLF diff --git a/Frameworks/OpenMPT/OpenMPT/build/dist.mk b/Frameworks/OpenMPT/OpenMPT/build/dist.mk index 0d475d5fa..d6f0465f5 100644 --- a/Frameworks/OpenMPT/OpenMPT/build/dist.mk +++ b/Frameworks/OpenMPT/OpenMPT/build/dist.mk @@ -1,4 +1,4 @@ -MPT_SVNVERSION=11626 -MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.5 -MPT_SVNDATE=2019-05-27T06:47:50.022790Z +MPT_SVNVERSION=12139 +MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.9 +MPT_SVNDATE=2019-10-02T14:33:59.345896Z diff --git a/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h b/Frameworks/OpenMPT/OpenMPT/build/svn_version/svn_version.h index e373c5233..9eac8dcd2 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 "11626" -#define OPENMPT_VERSION_REVISION 11626 +#define OPENMPT_VERSION_SVNVERSION "12139" +#define OPENMPT_VERSION_REVISION 12139 #define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0 -#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.5" -#define OPENMPT_VERSION_DATE "2019-05-27T06:47:50.022790Z" +#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.9" +#define OPENMPT_VERSION_DATE "2019-10-02T14:33:59.345896Z" #define OPENMPT_VERSION_IS_PACKAGE 1 diff --git a/Frameworks/OpenMPT/OpenMPT/common/BuildSettings.h b/Frameworks/OpenMPT/OpenMPT/common/BuildSettings.h index 6e1354d56..ce631f794 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/BuildSettings.h +++ b/Frameworks/OpenMPT/OpenMPT/common/BuildSettings.h @@ -578,6 +578,10 @@ #define NO_DMO #endif +#if defined(ENABLE_ASM) || !defined(NO_VST) +#define MPT_ENABLE_ALIGNED_ALLOC +#endif + #if defined(MODPLUG_TRACKER) && !defined(MPT_BUILD_WINESUPPORT) && !defined(MPT_BUILD_WINESUPPORT_WRAPPER) @@ -731,6 +735,24 @@ + + +// standard library quirks + +#if MPT_CXX_AT_LEAST(17) +#if (MPT_COMPILER_GCC || MPT_COMPILER_CLANG) +// we need to detect the standard library via macro __GLIBCXX__ +#include +#endif +#if MPT_COMPILER_MSVC || MPT_GCC_BEFORE(8,1,0) || MPT_CLANG_BEFORE(5,0,0) || (MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) || (MPT_COMPILER_CLANG && defined(__GLIBCXX__)) || (MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) || MPT_OS_OPENBSD || MPT_OS_EMSCRIPTEN || MPT_OS_HAIKU || (defined(__clang__) && defined(_MSC_VER)) +#define MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC +#endif +#endif + + + + + // third-party library configuration #if defined(MODPLUG_TRACKER) diff --git a/Frameworks/OpenMPT/OpenMPT/common/CompilerDetect.h b/Frameworks/OpenMPT/OpenMPT/common/CompilerDetect.h index 0e7e36638..5087163c3 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/CompilerDetect.h +++ b/Frameworks/OpenMPT/OpenMPT/common/CompilerDetect.h @@ -58,7 +58,9 @@ #elif defined(_MSC_VER) #define MPT_COMPILER_MSVC 1 -#if (_MSC_VER >= 1921) +#if (_MSC_VER >= 1922) +#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,2) +#elif (_MSC_VER >= 1921) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,1) #elif (_MSC_VER >= 1920) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,0) @@ -230,6 +232,8 @@ //#elif TARGET_OS_MAC //#else //#endif +#elif defined(__HAIKU__) + #define MPT_OS_HAIKU 1 #elif defined(__ANDROID__) || defined(ANDROID) #define MPT_OS_ANDROID 1 #elif defined(__linux__) @@ -263,6 +267,9 @@ #ifndef MPT_OS_MACOSX_OR_IOS #define MPT_OS_MACOSX_OR_IOS 0 #endif +#ifndef MPT_OS_HAIKU +#define MPT_OS_HAIKU 0 +#endif #ifndef MPT_OS_ANDROID #define MPT_OS_ANDROID 0 #endif diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.cpp b/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.cpp index 362bd1200..faaa7d04a 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.cpp +++ b/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.cpp @@ -30,6 +30,10 @@ OPENMPT_NAMESPACE_BEGIN +#if defined(MPT_ENABLE_ALIGNED_ALLOC) + + + namespace mpt { @@ -56,7 +60,7 @@ void* align(std::size_t alignment, std::size_t size, void* &ptr, std::size_t &sp aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std::size_t alignment) { - #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) && !MPT_OS_EMSCRIPTEN + #if MPT_CXX_AT_LEAST(17) && !defined(MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC) std::size_t space = count * size; void* mem = std::aligned_alloc(alignment, space); if(!mem) @@ -64,7 +68,7 @@ aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std:: MPT_EXCEPTION_THROW_OUT_OF_MEMORY(); } return aligned_raw_memory{mem, mem}; - #elif MPT_COMPILER_MSVC + #elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER)) std::size_t space = count * size; void* mem = _aligned_malloc(space, alignment); if(!mem) @@ -103,9 +107,9 @@ aligned_raw_memory aligned_alloc_impl(std::size_t size, std::size_t count, std:: void aligned_free(aligned_raw_memory raw) { - #if MPT_CXX_AT_LEAST(17) && (!MPT_COMPILER_MSVC && !MPT_GCC_BEFORE(8,1,0) && !MPT_CLANG_BEFORE(5,0,0)) && !(MPT_COMPILER_GCC && defined(__GLIBCXX__) && (defined(__MINGW32__) || defined(__MINGW64__))) && !(MPT_COMPILER_CLANG && defined(__GLIBCXX__)) && !(MPT_COMPILER_CLANG && MPT_OS_MACOSX_OR_IOS) && !MPT_OS_EMSCRIPTEN + #if MPT_CXX_AT_LEAST(17) && !defined(MPT_COMPILER_QUIRK_NO_ALIGNEDALLOC) std::free(raw.mem); - #elif MPT_COMPILER_MSVC + #elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER)) _aligned_free(raw.mem); #else std::free(raw.mem); @@ -118,4 +122,8 @@ void aligned_free(aligned_raw_memory raw) +#endif // MPT_ENABLE_ALIGNED_ALLOC + + + OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.h b/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.h index f881be95a..42e93a3f3 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.h +++ b/Frameworks/OpenMPT/OpenMPT/common/mptAlloc.h @@ -95,6 +95,10 @@ std::unique_ptr make_unique(Args&&... args) +#if defined(MPT_ENABLE_ALIGNED_ALLOC) + + + namespace mpt { @@ -259,4 +263,8 @@ public: +#endif // MPT_ENABLE_ALIGNED_ALLOC + + + OPENMPT_NAMESPACE_END diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptFileIO.cpp b/Frameworks/OpenMPT/OpenMPT/common/mptFileIO.cpp index 4f957f361..eae979c7a 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptFileIO.cpp +++ b/Frameworks/OpenMPT/OpenMPT/common/mptFileIO.cpp @@ -515,7 +515,8 @@ InputFile::ContentsRef InputFile::Get() return result; } result.first.data = m_File.Lock(); - result.first.size = m_File.GetLength(); + if(result.first.data) + result.first.size = m_File.GetLength(); result.second = &m_Filename; return result; } diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptIO.h b/Frameworks/OpenMPT/OpenMPT/common/mptIO.h index d6b059abd..24825bd33 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptIO.h +++ b/Frameworks/OpenMPT/OpenMPT/common/mptIO.h @@ -74,16 +74,16 @@ bool Flush(std::ostream & f); template class WriteBuffer; template bool IsValid(WriteBuffer & f) { return IsValid(f.file()); } -template IO::Offset TellRead(WriteBuffer & f) { return TellRead(f.file()); } -template IO::Offset TellWrite(WriteBuffer & f) { return TellWrite(f.file()); } -template bool SeekBegin(WriteBuffer & f) { return SeekBegin(f.file()); } -template bool SeekEnd(WriteBuffer & f) { return SeekEnd(f.file()); } -template bool SeekAbsolute(WriteBuffer & f, IO::Offset pos) { return SeekAbsolute(f.file(), pos); } -template bool SeekRelative(WriteBuffer & f, IO::Offset off) { return SeekRelative(f.file(), off); } -template IO::Offset ReadRawImpl(WriteBuffer & f, mpt::byte * data, std::size_t size) { return ReadRawImpl(f.file(), data, size); } +template IO::Offset TellRead(WriteBuffer & f) { f.FlushLocal(); return TellRead(f.file()); } +template IO::Offset TellWrite(WriteBuffer & f) { return TellWrite(f.file()) + f.GetCurrentSize(); } +template bool SeekBegin(WriteBuffer & f) { f.FlushLocal(); return SeekBegin(f.file()); } +template bool SeekEnd(WriteBuffer & f) { f.FlushLocal(); return SeekEnd(f.file()); } +template bool SeekAbsolute(WriteBuffer & f, IO::Offset pos) { return f.FlushLocal(); SeekAbsolute(f.file(), pos); } +template bool SeekRelative(WriteBuffer & f, IO::Offset off) { return f.FlushLocal(); SeekRelative(f.file(), off); } +template IO::Offset ReadRawImpl(WriteBuffer & f, mpt::byte * data, std::size_t size) { f.FlushLocal(); return ReadRawImpl(f.file(), data, size); } template bool WriteRawImpl(WriteBuffer & f, const mpt::byte * data, std::size_t size) { return f.Write(mpt::as_span(data, size)); } -template bool IsEof(WriteBuffer & f) { return IsEof(f.file()); } -template bool Flush(WriteBuffer & f) { return Flush(f.file()); } +template bool IsEof(WriteBuffer & f) { f.FlushLocal(); return IsEof(f.file()); } +template bool Flush(WriteBuffer & f) { f.FlushLocal(); return Flush(f.file()); } @@ -627,6 +627,10 @@ public: { return size == buffer.size(); } + inline std::size_t GetCurrentSize() const + { + return size; + } inline bool Write(mpt::const_byte_span data) { bool result = true; diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.cpp b/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.cpp index f77ef17fb..a8f92ae6d 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.cpp +++ b/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.cpp @@ -17,7 +17,20 @@ #endif #if MPT_FORMAT_CXX17_INT +#if MPT_MSVC_AT_LEAST(2019,0) && MPT_MSVC_BEFORE(2019,2) +#if !(defined(UNICODE) || defined(_UNICODE)) +// work-around https://developercommunity.visualstudio.com/content/problem/629849/mfc-headers-conflict-with-c17-charconv-header-in-m.html +#pragma push_macro("_M2") +#undef _M2 +#endif +#endif #include +#if MPT_MSVC_AT_LEAST(2019,0) && MPT_MSVC_BEFORE(2019,2) +#if !(defined(UNICODE) || defined(_UNICODE)) +// work-around https://developercommunity.visualstudio.com/content/problem/629849/mfc-headers-conflict-with-c17-charconv-header-in-m.html +#pragma pop_macro("_M2") +#endif +#endif #endif // MPT_FORMAT_CXX17_INT #include #include diff --git a/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.h b/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.h index 56a5d6e15..2ddad8e71 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.h +++ b/Frameworks/OpenMPT/OpenMPT/common/mptStringFormat.h @@ -88,9 +88,6 @@ MPT_DEPRECATED std::string ToString(const wchar_t & x); // deprecated to catch p MPT_DEPRECATED std::string ToString(const mpt::ustring & x); // Unknown encoding. #endif #if defined(_MFC_VER) -MPT_DEPRECATED std::string ToString(const mpt::ustring & x); // Unknown encoding. -#endif -#if defined(_MFC_VER) MPT_DEPRECATED std::string ToString(const CString & x); #endif std::string ToString(const bool & x); diff --git a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h index 62f7a9c1e..ee67ed3c8 100644 --- a/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h +++ b/Frameworks/OpenMPT/OpenMPT/common/versionNumber.h @@ -20,8 +20,8 @@ OPENMPT_NAMESPACE_BEGIN //Version definitions. The only thing that needs to be changed when changing version number. #define VER_MAJORMAJOR 1 #define VER_MAJOR 28 -#define VER_MINOR 05 -#define VER_MINORMINOR 00 +#define VER_MINOR 07 +#define VER_MINORMINOR 04 //Numerical value of the version. #define MPT_VERSION_CURRENT MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR) diff --git a/Frameworks/OpenMPT/OpenMPT/examples/libopenmpt_example_cxx.cpp b/Frameworks/OpenMPT/OpenMPT/examples/libopenmpt_example_cxx.cpp index d08b2d3dc..b3eb4e70e 100644 --- a/Frameworks/OpenMPT/OpenMPT/examples/libopenmpt_example_cxx.cpp +++ b/Frameworks/OpenMPT/OpenMPT/examples/libopenmpt_example_cxx.cpp @@ -20,7 +20,22 @@ #include +#if (__cplusplus >= 201103L) +#if defined(__clang__) +#if ((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 40000) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-dynamic-exception-spec" +#endif +#endif +#endif #include +#if (__cplusplus >= 201103L) +#if defined(__clang__) +#if ((__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) >= 40000) +#pragma clang diagnostic pop +#endif +#endif +#endif #if ( defined( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) ) #if defined( __GNUC__ ) diff --git a/Frameworks/OpenMPT/OpenMPT/include/minimp3/OpenMPT.txt b/Frameworks/OpenMPT/OpenMPT/include/minimp3/OpenMPT.txt index 56fbd7922..31b85dc15 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/minimp3/OpenMPT.txt +++ b/Frameworks/OpenMPT/OpenMPT/include/minimp3/OpenMPT.txt @@ -1,4 +1,4 @@ minimp3 library from https://github.com/lieff/minimp3 -commit e9df0760e94044caded36a55d70ab4152134adc5 (2018-12-23) +commit 977514a6dfc4960d819a103f43b358e58ac6c28f (2019-07-24) The following changes have been made: * minimp3.c has been added diff --git a/Frameworks/OpenMPT/OpenMPT/include/minimp3/minimp3.h b/Frameworks/OpenMPT/OpenMPT/include/minimp3/minimp3.h index a878b12db..6015bb9fa 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/minimp3/minimp3.h +++ b/Frameworks/OpenMPT/OpenMPT/include/minimp3/minimp3.h @@ -767,41 +767,72 @@ static void L3_huffman(float *dst, bs_t *bs, const L3_gr_info_t *gr_info, const int sfb_cnt = gr_info->region_count[ireg++]; const int16_t *codebook = tabs + tabindex[tab_num]; int linbits = g_linbits[tab_num]; - do + if (linbits) { - np = *sfb++ / 2; - pairs_to_decode = MINIMP3_MIN(big_val_cnt, np); - one = *scf++; do { - int j, w = 5; - int leaf = codebook[PEEK_BITS(w)]; - while (leaf < 0) + np = *sfb++ / 2; + pairs_to_decode = MINIMP3_MIN(big_val_cnt, np); + one = *scf++; + do { - FLUSH_BITS(w); - w = leaf & 7; - leaf = codebook[PEEK_BITS(w) - (leaf >> 3)]; - } - FLUSH_BITS(leaf >> 8); - - for (j = 0; j < 2; j++, dst++, leaf >>= 4) - { - int lsb = leaf & 0x0F; - if (lsb == 15 && linbits) + int j, w = 5; + int leaf = codebook[PEEK_BITS(w)]; + while (leaf < 0) { - lsb += PEEK_BITS(linbits); - FLUSH_BITS(linbits); - CHECK_BITS; - *dst = one*L3_pow_43(lsb)*((int32_t)bs_cache < 0 ? -1: 1); - } else - { - *dst = g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; + FLUSH_BITS(w); + w = leaf & 7; + leaf = codebook[PEEK_BITS(w) - (leaf >> 3)]; } - FLUSH_BITS(lsb ? 1 : 0); - } - CHECK_BITS; - } while (--pairs_to_decode); - } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0); + FLUSH_BITS(leaf >> 8); + + for (j = 0; j < 2; j++, dst++, leaf >>= 4) + { + int lsb = leaf & 0x0F; + if (lsb == 15) + { + lsb += PEEK_BITS(linbits); + FLUSH_BITS(linbits); + CHECK_BITS; + *dst = one*L3_pow_43(lsb)*((int32_t)bs_cache < 0 ? -1: 1); + } else + { + *dst = g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; + } + FLUSH_BITS(lsb ? 1 : 0); + } + CHECK_BITS; + } while (--pairs_to_decode); + } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0); + } else + { + do + { + np = *sfb++ / 2; + pairs_to_decode = MINIMP3_MIN(big_val_cnt, np); + one = *scf++; + do + { + int j, w = 5; + int leaf = codebook[PEEK_BITS(w)]; + while (leaf < 0) + { + FLUSH_BITS(w); + w = leaf & 7; + leaf = codebook[PEEK_BITS(w) - (leaf >> 3)]; + } + FLUSH_BITS(leaf >> 8); + + for (j = 0; j < 2; j++, dst++, leaf >>= 4) + { + int lsb = leaf & 0x0F; + *dst = g_pow43[16 + lsb - 16*(bs_cache >> 31)]*one; + FLUSH_BITS(lsb ? 1 : 0); + } + CHECK_BITS; + } while (--pairs_to_decode); + } while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0); + } } for (np = 1 - big_val_cnt;; dst += 4) diff --git a/Frameworks/OpenMPT/OpenMPT/include/miniz/OpenMPT.txt b/Frameworks/OpenMPT/OpenMPT/include/miniz/OpenMPT.txt index e5519647d..7e5267471 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/miniz/OpenMPT.txt +++ b/Frameworks/OpenMPT/OpenMPT/include/miniz/OpenMPT.txt @@ -1,6 +1,6 @@ miniz DEFLATE implementation. https://github.com/richgel999/miniz -2.0.8 +2.1.0 Modifications for OpenMPT: * #define MINIZ_NO_STDIO has been set because OpenMPT does not need stdio functionality and miniz relies on secure-CRT file i/o functions in windows @@ -12,7 +12,7 @@ Modifications for OpenMPT: * Warning `warning: cast from 'const mz_uint8 *' (aka 'const unsigned char *') to 'const mz_uint32 *' (aka 'const unsigned int *') increases required alignment from 1 to 4 [-Wcast-align]` has been fixed. - * Prototypes of `tdefl_compressor_alloc` and `tinfl_decompressor_alloc` + * Definitions of `tdefl_compressor_alloc` and `tinfl_decompressor_alloc` have beeen fixed * Missing #ifndef MINIZ_NO_STDIO has been added to miniz.h. No further changes have been made. diff --git a/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.c b/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.c index ca380e5c0..1c9315957 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.c +++ b/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.c @@ -397,6 +397,32 @@ int mz_inflateInit(mz_streamp pStream) return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); } +int mz_inflateReset(mz_streamp pStream) +{ + inflate_state *pDecomp; + if (!pStream) + return MZ_STREAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + + pDecomp = (inflate_state *)pStream->state; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + /* pDecomp->m_window_bits = window_bits */; + + return MZ_OK; +} + int mz_inflate(mz_streamp pStream, int flush) { inflate_state *pState; @@ -1340,13 +1366,13 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES #ifdef MINIZ_UNALIGNED_USE_MEMCPY -static inline mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p) +static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p) { mz_uint16 ret; memcpy(&ret, p, sizeof(mz_uint16)); return ret; } -static inline mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p) +static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p) { mz_uint16 ret; memcpy(&ret, p, sizeof(mz_uint16)); @@ -1455,6 +1481,16 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */ #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN +#ifdef MINIZ_UNALIGNED_USE_MEMCPY +static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p) +{ + mz_uint32 ret; + memcpy(&ret, p, sizeof(mz_uint32)); + return ret; +} +#else +#define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p) +#endif static mz_bool tdefl_compress_fast(tdefl_compressor *d) { /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */ @@ -1489,12 +1525,12 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) { mz_uint cur_match_dist, cur_match_len = 1; mz_uint8 *pCur_dict = d->m_dict + cur_pos; - mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; + mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF; mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; mz_uint probe_pos = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)lookahead_pos; - if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) + if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((TDEFL_READ_UNALIGNED_WORD32(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) { const mz_uint16 *p = (const mz_uint16 *)pCur_dict; const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); @@ -1524,7 +1560,11 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d) cur_match_dist--; pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); +#ifdef MINIZ_UNALIGNED_USE_MEMCPY + memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist)); +#else *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; +#endif pLZ_code_buf += 3; *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); @@ -2143,6 +2183,7 @@ void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE); } +#ifndef MINIZ_NO_MALLOC /* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */ /* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */ /* structure size and allocation mechanism. */ @@ -2159,6 +2200,7 @@ void tdefl_compressor_free(tdefl_compressor *pComp) { MZ_FREE(pComp); } +#endif #ifdef _MSC_VER #pragma warning(pop) @@ -2692,8 +2734,12 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex const mz_uint8 *pSrc_end = pSrc + (counter & ~7); do { +#ifdef MINIZ_UNALIGNED_USE_MEMCPY + memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2); +#else ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; +#endif pOut_buf_cur += 8; } while ((pSrc += 8) < pSrc_end); if ((counter &= 7) < 3) @@ -2885,6 +2931,7 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, return result; } +#ifndef MINIZ_NO_MALLOC #if 0 // OpenMPT tinfl_decompressor *tinfl_decompressor_alloc() #else // OpenMPT @@ -2901,6 +2948,7 @@ void tinfl_decompressor_free(tinfl_decompressor *pDecomp) { MZ_FREE(pDecomp); } +#endif #ifdef __cplusplus } @@ -2969,8 +3017,8 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) #define MZ_FWRITE fwrite #define MZ_FTELL64 _ftelli64 #define MZ_FSEEK64 _fseeki64 -#define MZ_FILE_STAT_STRUCT _stat -#define MZ_FILE_STAT _stat +#define MZ_FILE_STAT_STRUCT _stat64 +#define MZ_FILE_STAT _stat64 #define MZ_FFLUSH fflush #define MZ_FREOPEN mz_freopen #define MZ_DELETE_FILE remove @@ -3004,7 +3052,7 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) #define MZ_FFLUSH fflush #define MZ_FREOPEN(f, m, s) freopen(f, m, s) #define MZ_DELETE_FILE remove -#elif defined(__GNUC__) && _LARGEFILE64_SOURCE +#elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE) #ifndef MINIZ_NO_TIME #include #endif @@ -3258,7 +3306,8 @@ static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zi size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; - memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); + if (n > 0) + memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); return MZ_TRUE; } @@ -3655,21 +3704,47 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag if (extra_size_remaining) { - const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; + const mz_uint8 *pExtra_data; + void* buf = NULL; + + if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n) + { + buf = MZ_MALLOC(ext_data_size); + if(buf==NULL) + return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED); + + if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); + } + + pExtra_data = (mz_uint8*)buf; + } + else + { + pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size; + } do { mz_uint32 field_id; mz_uint32 field_data_size; - if (extra_size_remaining < (sizeof(mz_uint16) * 2)) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + if (extra_size_remaining < (sizeof(mz_uint16) * 2)) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } field_id = MZ_READ_LE16(pExtra_data); field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); - if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) - return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) + { + MZ_FREE(buf); + return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); + } if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID) { @@ -3682,6 +3757,8 @@ static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flag pExtra_data += sizeof(mz_uint16) * 2 + field_data_size; extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; } while (extra_size_remaining); + + MZ_FREE(buf); } } @@ -4878,7 +4955,7 @@ size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)) { /* The file is stored or the caller has requested the compressed data, calc amount to return. */ - copied_to_caller = MZ_MIN( buf_size, pState->comp_remaining ); + copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining ); /* Zip is in memory....or requires reading from a file? */ if (pState->pZip->m_pState->m_pMem) @@ -5955,7 +6032,7 @@ static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX) return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE); - if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) + if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, (mz_uint16)(extra_size + user_extra_data_len), comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || @@ -5979,13 +6056,7 @@ static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) if (*pArchive_name == '/') return MZ_FALSE; - while (*pArchive_name) - { - if ((*pArchive_name == '\\') || (*pArchive_name == ':')) - return MZ_FALSE; - - pArchive_name++; - } + /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/ return MZ_TRUE; } @@ -6176,7 +6247,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, bit_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) @@ -6203,7 +6274,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n { if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) @@ -6296,7 +6367,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, user_extra_data_central, user_extra_data_central_len)) return MZ_FALSE; @@ -6307,8 +6378,7 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n return MZ_TRUE; } -#ifndef MINIZ_NO_STDIO -mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, +mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) { mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR; @@ -6321,6 +6391,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, mz_uint32 extra_size = 0; mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; mz_zip_internal_state *pState; + mz_uint64 file_ofs = 0; if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME)) gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; @@ -6376,7 +6447,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, if (!pState->m_zip64) { /* Bail early if the archive would obviously become too large */ - if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024 + MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF) { @@ -6423,7 +6494,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)(extra_size + user_extra_data_len), 0, 0, 0, method, gen_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) @@ -6447,7 +6518,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, { if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX)) return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); - if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) + if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, (mz_uint16)user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date)) return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) @@ -6485,11 +6556,12 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, while (uncomp_remaining) { mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); - if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) + if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); } + file_ofs += n; uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); uncomp_remaining -= n; cur_archive_file_ofs += n; @@ -6524,12 +6596,13 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, tdefl_status status; tdefl_flush flush = TDEFL_NO_FLUSH; - if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) + if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size) { mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); break; } + file_ofs += in_buf_size; uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); uncomp_remaining -= in_buf_size; @@ -6597,7 +6670,7 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL); } - if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size, + if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes, user_extra_data_central, user_extra_data_central_len)) return MZ_FALSE; @@ -6608,6 +6681,26 @@ mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, return MZ_TRUE; } +#ifndef MINIZ_NO_STDIO + +static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) +{ + MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque; + mz_int64 cur_ofs = MZ_FTELL64(pSrc_file); + + if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET)))) + return 0; + + return MZ_FREAD(pBuf, 1, n, pSrc_file); +} + +mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, + const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len) +{ + return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, size_to_add, pFile_time, pComment, comment_size, level_and_flags, + user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len); +} + mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) { MZ_FILE *pSrc_file = NULL; diff --git a/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.h b/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.h index 9745bf8d0..cfa411370 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.h +++ b/Frameworks/OpenMPT/OpenMPT/include/miniz/miniz.h @@ -1,4 +1,4 @@ -/* miniz.c 2.0.8 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing +/* miniz.c 2.1.0 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing See "unlicense" statement at the end of this file. Rich Geldreich , last updated Oct. 13, 2013 Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt @@ -24,7 +24,7 @@ zlib replacement in many apps: The z_stream struct, optional memory allocation callbacks deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound - inflateInit/inflateInit2/inflate/inflateEnd + inflateInit/inflateInit2/inflate/inflateReset/inflateEnd compress, compress2, compressBound, uncompress CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. Supports raw deflate streams or standard zlib streams with adler-32 checking. @@ -179,16 +179,20 @@ #endif // OpenMPT #endif // OpenMPT +/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */ +#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES) #if MINIZ_X86_OR_X64_CPU /* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */ #if 0 // OpenMPT #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 +#define MINIZ_UNALIGNED_USE_MEMCPY #else // OpenMPT #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 // OpenMPT #endif // OpenMPT #else #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 #endif +#endif #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) /* Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). */ @@ -247,11 +251,11 @@ enum MZ_DEFAULT_COMPRESSION = -1 }; -#define MZ_VERSION "10.0.3" -#define MZ_VERNUM 0xA030 +#define MZ_VERSION "10.1.0" +#define MZ_VERNUM 0xA100 #define MZ_VER_MAJOR 10 -#define MZ_VER_MINOR 0 -#define MZ_VER_REVISION 3 +#define MZ_VER_MINOR 1 +#define MZ_VER_REVISION 0 #define MZ_VER_SUBREVISION 0 #ifndef MINIZ_NO_ZLIB_APIS @@ -374,6 +378,9 @@ int mz_inflateInit(mz_streamp pStream); /* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). */ int mz_inflateInit2(mz_streamp pStream, int window_bits); +/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_inflateEnd() followed by mz_inflateInit()/mz_inflateInit2(). */ +int mz_inflateReset(mz_streamp pStream); + /* Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. */ /* Parameters: */ /* pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. */ @@ -457,6 +464,7 @@ typedef void *const voidpc; #define compressBound mz_compressBound #define inflateInit mz_inflateInit #define inflateInit2 mz_inflateInit2 +#define inflateReset mz_inflateReset #define inflate mz_inflate #define inflateEnd mz_inflateEnd #define uncompress mz_uncompress @@ -750,15 +758,13 @@ mz_uint32 tdefl_get_adler32(tdefl_compressor *d); /* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */ mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); +#ifndef MINIZ_NO_MALLOC /* Allocate the tdefl_compressor structure in C so that */ /* non-C language bindings to tdefl_ API don't need to worry about */ /* structure size and allocation mechanism. */ -#if 0 // OpenMPT -tdefl_compressor *tdefl_compressor_alloc(); -#else // OpenMPT -tdefl_compressor *tdefl_compressor_alloc(void); // OpenMPT -#endif // OpenMPT +tdefl_compressor *tdefl_compressor_alloc(void); void tdefl_compressor_free(tdefl_compressor *pComp); +#endif #ifdef __cplusplus } @@ -806,16 +812,13 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; +#ifndef MINIZ_NO_MALLOC /* Allocate the tinfl_decompressor structure in C so that */ /* non-C language bindings to tinfl_ API don't need to worry about */ /* structure size and allocation mechanism. */ - -#if 0 // OpenMPT -tinfl_decompressor *tinfl_decompressor_alloc(); -#else // OpenMPT -tinfl_decompressor *tinfl_decompressor_alloc(void); // OpenMPT -#endif // OpenMPT +tinfl_decompressor *tinfl_decompressor_alloc(void); void tinfl_decompressor_free(tinfl_decompressor *pDecomp); +#endif /* Max size of LZ dictionary. */ #define TINFL_LZ_DICT_SIZE 32768 @@ -1292,6 +1295,12 @@ mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_n mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len); +/* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */ +/* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/ +mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, + const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len, + const char *user_extra_data_central, mz_uint user_extra_data_central_len); + #ifndef MINIZ_NO_STDIO /* Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. */ /* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */ diff --git a/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/OpenMPT.txt b/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/OpenMPT.txt index 5a9b8d3f5..44eeb833b 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/OpenMPT.txt +++ b/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/OpenMPT.txt @@ -1,6 +1,6 @@ This folder contains the stb_vorbis library from -https://github.com/nothings/stb/blob/master/stb_vorbis.c v1.16 -commit 2c2908f50515dcd939f24be261c3ccbcd277bb49 (2019-03-05) +https://github.com/nothings/stb/blob/master/stb_vorbis.c v1.17 +commit 130f28df68c3fdbf043c4275260ba1c870495b5b (2019-08-09) Modifications: * Use of alloca has been replaced with malloc, as alloca is not in C99 and diff --git a/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/stb_vorbis.c b/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/stb_vorbis.c index 1a81d80c8..eb9bf1cfc 100644 --- a/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/stb_vorbis.c +++ b/Frameworks/OpenMPT/OpenMPT/include/stb_vorbis/stb_vorbis.c @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.16 - public domain +// Ogg Vorbis audio decoder - v1.17 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -30,9 +30,10 @@ // Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Phillip Bennefall Rohit Thiago Goulart // manxorist@github saga musix github:infatum -// Timur Gagiev +// Timur Gagiev Maxwell Koo // // Partial history: +// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure) // 1.16 - 2019-03-04 - fix warnings // 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found // 1.14 - 2018-02-11 - delete bogus dealloca usage @@ -1211,8 +1212,10 @@ static int lookup1_values(int entries, int dim) int r = (int) floor(exp((float) log((float) entries) / dim)); if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; ++r; // floor() to avoid _ftol() when non-CRT - assert(pow((float) r+1, dim) > entries); - assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above + if (pow((float) r+1, dim) <= entries) + return -1; + if ((int) floor(pow((float) r, dim)) > entries) + return -1; return r; } @@ -2022,7 +2025,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y ady -= abs(base) * adx; if (x1 > n) x1 = n; if (x < x1) { - LINE_OP(output[x], inverse_db_table[y]); + LINE_OP(output[x], inverse_db_table[y&255]); for (++x; x < x1; ++x) { err += ady; if (err >= adx) { @@ -2030,7 +2033,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y y += sy; } else y += base; - LINE_OP(output[x], inverse_db_table[y]); + LINE_OP(output[x], inverse_db_table[y&255]); } } } @@ -3057,7 +3060,6 @@ static float *get_window(vorb *f, int len) len <<= 1; if (len == f->blocksize_0) return f->window[0]; if (len == f->blocksize_1) return f->window[1]; - assert(0); return NULL; } @@ -3463,6 +3465,7 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) if (f->previous_length) { int i,j, n = f->previous_length; float *w = get_window(f, n); + if (w == NULL) return 0; for (i=0; i < f->channels; ++i) { for (j=0; j < n; ++j) f->channel_buffers[i][left+j] = @@ -3704,6 +3707,7 @@ static int start_decoder(vorb *f) while (current_entry < c->entries) { int limit = c->entries - current_entry; int n = get_bits(f, ilog(limit)); + if (current_length >= 32) return error(f, VORBIS_invalid_setup); if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); } memset(lengths + current_entry, current_length, n); current_entry += n; @@ -3807,7 +3811,9 @@ static int start_decoder(vorb *f) c->value_bits = get_bits(f, 4)+1; c->sequence_p = get_bits(f,1); if (c->lookup_type == 1) { - c->lookup_values = lookup1_values(c->entries, c->dimensions); + int values = lookup1_values(c->entries, c->dimensions); + if (values < 0) return error(f, VORBIS_invalid_setup); + c->lookup_values = (uint32) values; } else { c->lookup_values = c->entries * c->dimensions; } @@ -3943,6 +3949,9 @@ static int start_decoder(vorb *f) p[j].id = j; } qsort(p, g->values, sizeof(p[0]), point_compare); + for (j=0; j < g->values-1; ++j) + if (p[j].x == p[j+1].x) + return error(f, VORBIS_invalid_setup); for (j=0; j < g->values; ++j) g->sorted_order[j] = (uint8) p[j].id; // precompute the neighbors @@ -4034,6 +4043,7 @@ static int start_decoder(vorb *f) max_submaps = m->submaps; if (get_bits(f,1)) { m->coupling_steps = get_bits(f,8)+1; + if (m->coupling_steps > f->channels) return error(f, VORBIS_invalid_setup); for (k=0; k < m->coupling_steps; ++k) { m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); m->chan[k].angle = get_bits(f, ilog(f->channels-1)); @@ -5400,6 +5410,12 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13223, -13223 + found with Mayhem by ForAllSecure + 1.16 - 2019-03-04 - fix warnings + 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found + 1.14 - 2018-02-11 - delete bogus dealloca usage + 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files 1.11 - 2017-07-23 - fix MinGW compilation 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/doc/in_openmpt.txt b/Frameworks/OpenMPT/OpenMPT/libopenmpt/doc/in_openmpt.txt index d5035f98f..94ef4095b 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/doc/in_openmpt.txt +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/doc/in_openmpt.txt @@ -10,8 +10,8 @@ libopenmpt. Installation ------------ -"in_openmpt.dll" and "openmpt-mpg123.dll" must both be placed into the Winamp -"Plugins" directory. +"in_openmpt.dll" must be placed into the Winamp "Plugins" directory, and +"openmpt-mpg123.dll" must be placed into the Winamp directory. See https://lib.openmpt.org/ for documentation, FAQ and other details. diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md index 8aee41ce4..6b4c678f4 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/dox/changelog.md @@ -5,6 +5,56 @@ Changelog {#changelog} For fully detailed change log, please see the source repository directly. This is just a high-level summary. +### libopenmpt 0.4.9 (2019-10-02) + + * [**Sec**] libmodplug: C API: Limit the length of strings copied to the + output buffer of `ModPlug_InstrumentName()` and `ModPlug_SampleName()` to 32 + bytes (including terminating null) as is done by original libmodplug. This + avoids potential buffer overflows in software relying on this limit instead + of querying the required buffer size beforehand. libopenmpt can return + strings longer than 32 bytes here beacuse the internal limit of 32 bytes + applies to strings encoded in arbitrary character encodings but the API + returns them converted to UTF-8, which can be longer. (reported by Antonio + Morales Maldonado of Semmle Security Research Team) (r12129) + * [**Sec**] libmodplug: C++ API: Do not return 0 in + `CSoundFile::GetSampleName()` and `CSoundFile::GetInstrumentName()` when a + null output pointer is provided. This behaviour differed from libmodplug and + made it impossible to determine the required buffer size. (r12130) + +### libopenmpt 0.4.8 (2019-09-30) + + * [**Sec**] Possible crash due to out-of-bounds read when playing an OPL note + with active filter in S3M or MPTM files (r12118). + +### libopenmpt 0.4.7 (2019-09-23) + + * [**Bug**] Compilation fix for various platforms that do not provide + `std::aligned_alloc` in C++17 mode. The problematic dependency has been + removed. This should fix build problems on MinGW, OpenBSD, Haiku, and others + for good. + + * J2B: Ignore notes with non-existing instrument (fixes Ending.j2b). + + * mpg123: Update to v1.25.13 (2019-08-24). + * ogg: Update to v1.3.4. (2019-08-31). + * flac: Update to v1.3.3. (2019-08-04). + +### libopenmpt 0.4.6 (2019-08-10) + + * [**Bug**] Compilation fix for OpenBSD. + * [**Bug**] Compilation fix for NO_PLUGINS being defined. + + * in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into + the Winamp directory. + + * Detect IT files unpacked with early UNMO3 versions. + + * mpg123: Update to v1.25.11 (2019-07-18). + * minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f + (2019-07-24). + * miniz: Update to v2.1.0 (2019-05-05). + * stb_vorbis: Update to v1.17 (2019-08-09). + ### libopenmpt 0.4.5 (2019-05-27) * [**Sec**] Possible crash during playback due out-of-bounds read in XM and diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug.c b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug.c index d5b469552..da13edc3f 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug.c +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug.c @@ -478,53 +478,35 @@ LIBOPENMPT_MODPLUG_API unsigned int ModPlug_NumChannels(ModPlugFile* file) LIBOPENMPT_MODPLUG_API unsigned int ModPlug_SampleName(ModPlugFile* file, unsigned int qual, char* buff) { const char* str; - unsigned int retval; - size_t tmpretval; + char buf[32]; if(!file) return 0; str = openmpt_module_get_sample_name(file->mod,qual-1); - if(!str){ - if(buff){ - *buff = '\0'; - } - return 0; + memset(buf,0,32); + if(str){ + strncpy(buf,str,31); + openmpt_free_string(str); } - tmpretval = strlen(str); - if(tmpretval>=INT_MAX){ - tmpretval = INT_MAX-1; - } - retval = (int)tmpretval; if(buff){ - memcpy(buff,str,retval+1); - buff[retval] = '\0'; + strncpy(buff,buf,32); } - openmpt_free_string(str); - return retval; + return (unsigned int)strlen(buf); } LIBOPENMPT_MODPLUG_API unsigned int ModPlug_InstrumentName(ModPlugFile* file, unsigned int qual, char* buff) { const char* str; - unsigned int retval; - size_t tmpretval; + char buf[32]; if(!file) return 0; str = openmpt_module_get_instrument_name(file->mod,qual-1); - if(!str){ - if(buff){ - *buff = '\0'; - } - return 0; + memset(buf,0,32); + if(str){ + strncpy(buf,str,31); + openmpt_free_string(str); } - tmpretval = strlen(str); - if(tmpretval>=INT_MAX){ - tmpretval = INT_MAX-1; - } - retval = (int)tmpretval; if(buff){ - memcpy(buff,str,retval+1); - buff[retval] = '\0'; + strncpy(buff,buf,32); } - openmpt_free_string(str); - return retval; + return (unsigned int)strlen(buf); } LIBOPENMPT_MODPLUG_API ModPlugNote* ModPlug_GetPattern(ModPlugFile* file, int pattern, unsigned int* numrows) diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug_cpp.cpp b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug_cpp.cpp index a1d36e5a5..f487339f2 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug_cpp.cpp +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_modplug_cpp.cpp @@ -304,9 +304,6 @@ void CSoundFile::SetCurrentOrder( UINT nOrder ) { UINT CSoundFile::GetSampleName( UINT nSample, LPSTR s ) const { mpcpplog(); - if ( !s ) { - return 0; - } char buf[32]; std::memset( buf, 0, 32 ); if ( mod ) { @@ -315,15 +312,14 @@ UINT CSoundFile::GetSampleName( UINT nSample, LPSTR s ) const { std::strncpy( buf, names[ nSample - 1 ].c_str(), 31 ); } } - std::memcpy( s, buf, 32 ); + if ( s ) { + std::strncpy( s, buf, 32 ); + } return static_cast( std::strlen( buf ) ); } UINT CSoundFile::GetInstrumentName( UINT nInstr, LPSTR s ) const { mpcpplog(); - if ( !s ) { - return 0; - } char buf[32]; std::memset( buf, 0, 32 ); if ( mod ) { @@ -332,7 +328,9 @@ UINT CSoundFile::GetInstrumentName( UINT nInstr, LPSTR s ) const { std::strncpy( buf, names[ nInstr - 1 ].c_str(), 31 ); } } - std::memcpy( s, buf, 32 ); + if ( s ) { + std::strncpy( s, buf, 32 ); + } return static_cast( std::strlen( buf ) ); } diff --git a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h index 787d442a7..686c35166 100644 --- a/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h +++ b/Frameworks/OpenMPT/OpenMPT/libopenmpt/libopenmpt_version.h @@ -19,7 +19,7 @@ /*! \brief libopenmpt minor version number */ #define OPENMPT_API_VERSION_MINOR 4 /*! \brief libopenmpt patch version number */ -#define OPENMPT_API_VERSION_PATCH 5 +#define OPENMPT_API_VERSION_PATCH 9 /*! \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 6bcc6d823..59dd99713 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=4 -LIBOPENMPT_VERSION_PATCH=5 +LIBOPENMPT_VERSION_PATCH=9 LIBOPENMPT_VERSION_PREREL= LIBOPENMPT_LTVER_CURRENT=1 -LIBOPENMPT_LTVER_REVISION=5 +LIBOPENMPT_LTVER_REVISION=9 LIBOPENMPT_LTVER_AGE=1 diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Dither.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Dither.cpp index c09bcc45e..697065d76 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Dither.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Dither.cpp @@ -61,7 +61,8 @@ void X86_Dither(int32 *pBuffer, uint32 nSamples, uint32 nBits, DitherModPlugStat mov ecx, nBits // ecx = number of bits of noise mov edi, gDitherA // Noise generation mov ebx, gDitherB - add ecx, MIXING_ATTENUATION+1 + add ecx, MIXING_ATTENUATION + add ecx, 1 push ebp mov ebp, eax noiseloop: @@ -117,7 +118,7 @@ static void C_Dither(int32 *pBuffer, std::size_t count, uint32 nBits, DitherModP while(count--) { - *pBuffer += dither_rand(a, b) >> (nBits + MIXING_ATTENUATION + 1); + *pBuffer += mpt::rshift_signed(dither_rand(a, b), (nBits + MIXING_ATTENUATION + 1)); pBuffer++; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp index 381b91801..39d10a012 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Dlsbank.cpp @@ -563,7 +563,7 @@ bool CDLSBank::IsDLSBank(const mpt::PathString &filename) const DLSINSTRUMENT *CDLSBank::FindInstrument(bool isDrum, uint32 bank, uint32 program, uint32 key, uint32 *pInsNo) const { - if (m_Instruments.empty()) return NULL; + if (m_Instruments.empty()) return nullptr; for (uint32 iIns=0; iIns(Util::muldivr(p.chPitchCorrection, 128, 100)); - if (((p.sfSampleType & 0x7FFF) <= 4) && (p.dwStart < 0x08000000) && (p.dwEnd >= p.dwStart+8)) + if (((p.sfSampleType & 0x7FFF) <= 4) && (p.dwEnd >= p.dwStart + 4)) { dlsSmp.dwLen = (p.dwEnd - p.dwStart) * 2; if ((p.dwEndloop > p.dwStartloop + 7) && (p.dwStartloop >= p.dwStart)) @@ -1192,7 +1192,6 @@ bool CDLSBank::Open(FileReader file) m_szFileName = file.GetFileName(); file.Rewind(); - const uint8 *lpMemFile = file.GetRawData(); size_t dwMemLength = file.GetLength(); size_t dwMemPos = 0; if(!file.CanRead(256)) @@ -1397,13 +1396,14 @@ bool CDLSBank::Open(FileReader file) Log("ptbl not present: building table (%d wavelinks)...\n", m_nMaxWaveLink); #endif m_WaveForms.reserve(m_nMaxWaveLink); - dwMemPos = m_dwWavePoolOffset; - while (dwMemPos + sizeof(IFFCHUNK) < dwMemLength) + file.Seek(m_dwWavePoolOffset); + while(m_WaveForms.size() < m_nMaxWaveLink && file.CanRead(sizeof(IFFCHUNK))) { - IFFCHUNK *pchunk = (IFFCHUNK *)(lpMemFile + dwMemPos); - if (pchunk->id == IFFID_LIST) m_WaveForms.push_back(dwMemPos - m_dwWavePoolOffset); - dwMemPos += 8 + pchunk->len; - if (m_WaveForms.size() >= m_nMaxWaveLink) break; + IFFCHUNK chunk; + file.ReadStruct(chunk); + if (chunk.id == IFFID_LIST) + m_WaveForms.push_back(file.GetPosition() - m_dwWavePoolOffset - sizeof(IFFCHUNK)); + file.Skip(chunk.len); } #ifdef DLSBANK_LOG Log("Found %d waveforms\n", m_WaveForms.size()); @@ -1467,13 +1467,13 @@ bool CDLSBank::ExtractWaveForm(uint32 nIns, uint32 nRgn, std::vector &wav return false; } - long dwOffset = mpt::saturate_cast(m_WaveForms[nWaveLink] + m_dwWavePoolOffset); mpt::ifstream f(m_szFileName, std::ios::binary); if(!f) { return false; } - if (mpt::IO::SeekAbsolute(f, dwOffset)) + mpt::IO::Offset sampleOffset = mpt::saturate_cast(m_WaveForms[nWaveLink] + m_dwWavePoolOffset); + if(mpt::IO::SeekAbsolute(f, sampleOffset)) { if (m_nType & SOUNDBANK_TYPE_SF2) { diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp index 223dc6ea5..069e4a47e 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_it.cpp @@ -594,23 +594,25 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) uint32 minPtr = Util::MaxValueOfType(minPtr); for(uint32 pos : insPos) { - if(pos > 0) minPtr = std::min(minPtr, pos); + if(pos > 0 && pos < minPtr) minPtr = pos; } for(uint32 pos : smpPos) { - if(pos > 0) minPtr = std::min(minPtr, pos); + if(pos > 0 && pos < minPtr) minPtr = pos; } for(uint32 pos : patPos) { - if(pos > 0) minPtr = std::min(minPtr, pos); + if(pos > 0 && pos < minPtr) minPtr = pos; } if(fileHeader.special & ITFileHeader::embedSongMessage) { minPtr = std::min(minPtr, fileHeader.msgoffset); } - const bool possiblyUNMO3 = fileHeader.cmwt == 0x0214 && fileHeader.cwtv == 0x0214 && fileHeader.highlight_major == 0 && fileHeader.highlight_minor == 0 - && fileHeader.pwd == 0 && fileHeader.reserved == 0 && (fileHeader.flags & (ITFileHeader::useMIDIPitchController | ITFileHeader::reqEmbeddedMIDIConfig)) == 0; + const bool possiblyUNMO3 = fileHeader.cmwt == 0x0214 && (fileHeader.cwtv == 0x0214 || fileHeader.cwtv == 0) + && fileHeader.highlight_major == 0 && fileHeader.highlight_minor == 0 + && fileHeader.pwd == 0 && fileHeader.reserved == 0 + && (fileHeader.flags & (ITFileHeader::useMIDIPitchController | ITFileHeader::reqEmbeddedMIDIConfig)) == 0; if(possiblyUNMO3 && fileHeader.insnum == 0 && fileHeader.smpnum > 0 && file.GetPosition() + 4 * smpPos.size() + 2 <= minPtr) { @@ -634,6 +636,11 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) } } + if(possiblyUNMO3 && fileHeader.cwtv == 0) + { + madeWithTracker = U_("UNMO3 v0/1"); + } + // Reading IT Edit History Info // This is only supposed to be present if bit 1 of the special flags is set. // However, old versions of Schism and probably other trackers always set this bit @@ -812,14 +819,14 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) // External sample in MPTM file size_t strLen; file.ReadVarInt(strLen); - if(loadFlags & loadSampleData) + if((loadFlags & loadSampleData) && strLen) { std::string filenameU8; file.ReadString(filenameU8, strLen); #if defined(MPT_EXTERNAL_SAMPLES) SetSamplePath(i + 1, mpt::PathString::FromUTF8(filenameU8)); #elif !defined(LIBOPENMPT_BUILD_TEST) - AddToLog(LogWarning, mpt::format(U_("Loading external sample %1 ('%2') failed: External samples are not supported."))(i, mpt::ToUnicode(mpt::CharsetUTF8, filenameU8))); + AddToLog(LogWarning, mpt::format(U_("Loading external sample %1 ('%2') failed: External samples are not supported."))(i + 1, mpt::ToUnicode(mpt::CharsetUTF8, filenameU8))); #endif // MPT_EXTERNAL_SAMPLES } else { @@ -1170,7 +1177,7 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) && m_nSamples > 0 && !strcmp(Samples[1].filename, "XXXXXXXX.YYY")) { madeWithTracker = U_("CheeseTracker"); - } else if(fileHeader.cwtv == 0) + } else if(fileHeader.cwtv == 0 && madeWithTracker.empty()) { madeWithTracker = U_("Unknown"); } else if(fileHeader.cmwt < 0x0300 && madeWithTracker.empty()) @@ -1629,7 +1636,7 @@ bool CSoundFile::SaveIT(std::ostream &f, const mpt::PathString &filename, bool c uint32 len = 0; // Maximum 7 bytes per cell, plus end of row marker, so this buffer is always large enough to cover one row. uint8 buf[7 * MAX_BASECHANNELS + 1]; - const ModCommand *m = Patterns[pat].GetRow(row); + const ModCommand *m = Patterns[pat].GetpModCommand(row, 0); for(CHANNELINDEX ch = 0; ch < maxChannels; ch++, m++) { diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mid.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mid.cpp index 013e741a7..02b1f1029 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mid.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mid.cpp @@ -516,6 +516,7 @@ static void MIDINoteOff(MidiChannelState &midiChn, std::vector uint8 midiCh = modChnStatus[chn].midiCh; modChnStatus[chn].note = NOTE_NONE; + modChnStatus[chn].sustained = false; midiChn.noteOn[note] = CHANNELINDEX_INVALID; ModCommand &m = patRow[chn]; if(m.note == NOTE_NONE) @@ -953,7 +954,7 @@ bool CSoundFile::ReadMID(FileReader &file, ModLoadingFlags loadFlags) // Release notes that are still being held after note-off for(const auto &chnState : modChnStatus) { - if(chnState.midiCh == midiCh && chnState.sustained) + if(chnState.midiCh == midiCh && chnState.sustained && chnState.note != NOTE_NONE) { MIDINoteOff(midiChnStatus[midiCh], modChnStatus, chnState.note - NOTE_MIN, delay, patRow, drumChns); } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp index 5233d50e5..d9401542f 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mo3.cpp @@ -210,10 +210,16 @@ struct MO3Instrument } if(mptIns.nMidiChannel != MidiNoChannel) { - if(mptIns.wMidiBank < 128) - mptIns.wMidiBank = midiBank + 1; - if(mptIns.nMidiProgram < 128) + if(type == MOD_TYPE_XM) + { mptIns.nMidiProgram = midiPatch + 1; + } else + { + if(midiBank < 128) + mptIns.wMidiBank = midiBank + 1; + if(midiPatch < 128) + mptIns.nMidiProgram = midiPatch + 1; + } mptIns.midiPWD = midiBend; } @@ -1394,7 +1400,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) sampleData.Seek(frame.frameSize); mpegData = sampleData.ReadChunk(sampleData.BytesLeft()); } - + if(ReadMP3Sample(smp, mpegData, true, true) || ReadMediaFoundationSample(smp, mpegData, true)) { if(smpHeader.encoderDelay > 0 && smpHeader.encoderDelay < sample.GetSampleSizeInBytes()) @@ -1579,10 +1585,9 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) sampleChunk.chunk.Rewind(); FileReader::PinnedRawDataView sampleChunkView = sampleChunk.chunk.GetPinnedRawDataView(); - mergedData.insert(mergedData.end(), mpt::byte_cast(sampleChunkView.begin()), mpt::byte_cast(sampleChunkView.end())); + mergedData.insert(mergedData.end(), mpt::byte_cast(sampleChunkView.begin()), mpt::byte_cast(sampleChunkView.end())); #endif - } FileReader mergedDataChunk(mpt::byte_cast(mpt::as_span(mergedData))); @@ -1647,10 +1652,10 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) { if(sample.uFlags[CHN_16BIT]) { - CopyChannelToInterleaved >(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); + CopyChannelToInterleaved>(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); } else { - CopyChannelToInterleaved >(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); + CopyChannelToInterleaved>(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); } } } @@ -1687,7 +1692,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) if(sharedHeader) { FileReader::PinnedRawDataView headChunkView = headerChunk.GetPinnedRawDataView(initialRead); - vorb = stb_vorbis_open_pushdata(mpt::byte_cast(headChunkView.data()), mpt::saturate_cast(headChunkView.size()), &consumed, &error, nullptr); + vorb = stb_vorbis_open_pushdata(mpt::byte_cast(headChunkView.data()), mpt::saturate_cast(headChunkView.size()), &consumed, &error, nullptr); headerChunk.Skip(consumed); } FileReader::PinnedRawDataView sampleDataView = sampleData.GetPinnedRawDataView(); @@ -1695,7 +1700,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) std::size_t dataLeft = sampleDataView.size(); if(!sharedHeader) { - vorb = stb_vorbis_open_pushdata(mpt::byte_cast(data), mpt::saturate_cast(dataLeft), &consumed, &error, nullptr); + vorb = stb_vorbis_open_pushdata(mpt::byte_cast(data), mpt::saturate_cast(dataLeft), &consumed, &error, nullptr); sampleData.Skip(consumed); data += consumed; dataLeft -= consumed; @@ -1711,7 +1716,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) { int channels = 0, decodedSamples = 0; float **output; - consumed = stb_vorbis_decode_frame_pushdata(vorb, mpt::byte_cast(data), mpt::saturate_cast(dataLeft), &channels, &output, &decodedSamples); + consumed = stb_vorbis_decode_frame_pushdata(vorb, mpt::byte_cast(data), mpt::saturate_cast(dataLeft), &channels, &output, &decodedSamples); sampleData.Skip(consumed); data += consumed; dataLeft -= consumed; @@ -1721,9 +1726,9 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags) for(int chn = 0; chn < channels; chn++) { if(sample.uFlags[CHN_16BIT]) - CopyChannelToInterleaved >(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); + CopyChannelToInterleaved>(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); else - CopyChannelToInterleaved >(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); + CopyChannelToInterleaved>(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); } } offset += decodedSamples; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp index 073fd7b2d..43d5976a9 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mod.cpp @@ -456,14 +456,14 @@ struct PT36IffChunk // IFF chunk names enum ChunkIdentifiers { - idVERS = MagicBE("VERS"), - idINFO = MagicBE("INFO"), - idCMNT = MagicBE("CMNT"), - idPTDT = MagicBE("PTDT"), + idVERS = MagicBE("VERS"), + idINFO = MagicBE("INFO"), + idCMNT = MagicBE("CMNT"), + idPTDT = MagicBE("PTDT"), }; - uint32be signature; // IFF chunk name - uint32be chunksize; // chunk size without header + uint32be signature; // IFF chunk name + uint32be chunksize; // chunk size without header }; MPT_BINARY_STRUCT(PT36IffChunk, 8) @@ -521,9 +521,9 @@ static uint32 ReadSample(FileReader &file, MODSampleHeader &sampleHeader, ModSam // Parse the order list to determine how many patterns are used in the file. static PATTERNINDEX GetNumPatterns(FileReader &file, ModSequence &Order, ORDERINDEX numOrders, SmpLength totalSampleLen, CHANNELINDEX &numChannels, bool checkForWOW) { - PATTERNINDEX numPatterns = 0; // Total number of patterns in file (determined by going through the whole order list) with pattern number < 128 - PATTERNINDEX officialPatterns = 0; // Number of patterns only found in the "official" part of the order list (i.e. order positions < claimed order length) - PATTERNINDEX numPatternsIllegal = 0; // Total number of patterns in file, also counting in "invalid" pattern indexes >= 128 + PATTERNINDEX numPatterns = 0; // Total number of patterns in file (determined by going through the whole order list) with pattern number < 128 + PATTERNINDEX officialPatterns = 0; // Number of patterns only found in the "official" part of the order list (i.e. order positions < claimed order length) + PATTERNINDEX numPatternsIllegal = 0; // Total number of patterns in file, also counting in "invalid" pattern indexes >= 128 for(ORDERINDEX ord = 0; ord < 128; ord++) { @@ -893,7 +893,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags) pat /= 2u; } } - + // Restart position sanity checks realOrders--; Order().SetRestartPos(fileHeader.restartPos); @@ -918,7 +918,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags) // is the maximum possible sample pre-amp without getting distortion (Compatible mix levels given). // The more channels we have, the less likely it is that all of them are used at the same time, though, so cap at 32... m_nSamplePreAmp = Clamp(256 / m_nChannels, 32, 128); - m_SongFlags.reset(); // SONG_ISAMIGA will be set conditionally + m_SongFlags.reset(); // SONG_ISAMIGA will be set conditionally // Setup channel pan positions and volume SetupMODPanning(); @@ -930,10 +930,10 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags) // - Detect 7-bit panning. bool onlyAmigaNotes = true; bool fix7BitPanning = false; - uint8 maxPanning = 0; // For detecting 8xx-as-sync + uint8 maxPanning = 0; // For detecting 8xx-as-sync if(!isNoiseTracker) { - bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning + bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning isNoiseTracker = isMdKd; for(PATTERNINDEX pat = 0; pat < numPatterns; pat++) { @@ -963,7 +963,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags) extendedPanning = true; } else if(m.command == 0x0E && (m.param & 0xF0) == 0x80) { - maxPanning = std::max(maxPanning, m.param << 4); + maxPanning = std::max(maxPanning, (m.param & 0x0F) << 4); } } } @@ -1342,7 +1342,6 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders) totalSampleLen += sampleHeader.length; allVolumes |= sampleHeader.volume; - } // Reject any files with no (or only silent) samples at all, as this might just be a random binary file (e.g. ID3 tags with tons of padding) @@ -1364,7 +1363,7 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders) { return false; } - + // No playable song, and lots of null values => most likely a sparse binary file but not a module if(fileHeaders.fileHeader.restartPos == 0 && fileHeaders.fileHeader.numOrders == 0 && maxPattern == 0) { @@ -2095,7 +2094,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) } // First chunk includes "MODL" magic in size iffHead.chunksize -= 4; - + do { // All chunk sizes include chunk header @@ -2104,7 +2103,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) { return true; } - + FileReader chunk = file.ReadChunk(iffHead.chunksize); if(!chunk.IsValid()) { @@ -2120,15 +2119,15 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) chunk.ReadString(version, mpt::CharsetISO8859_1, iffHead.chunksize - 6); } break; - + case PT36IffChunk::idINFO: infoOk = chunk.ReadStruct(info); break; - + case PT36IffChunk::idCMNT: commentChunk = chunk; break; - + case PT36IffChunk::idPTDT: ok = ReadMOD(chunk, loadFlags); break; @@ -2139,7 +2138,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) { version = U_("3.6"); } - + // both an info chunk and a module are required if(ok && infoOk) { @@ -2149,10 +2148,10 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) m_nSamplePreAmp = std::min(64, info.volume); if(info.tempo != 0 && !vblank) m_nDefaultTempo.Set(info.tempo); - + if(info.name[0]) mpt::String::Read(m_songName, info.name); - + if(IsInRange(info.dateMonth, 1, 12) && IsInRange(info.dateDay, 1, 31) && IsInRange(info.dateHour, 0, 23) && IsInRange(info.dateMinute, 0, 59) && IsInRange(info.dateSecond, 0, 59)) { @@ -2179,14 +2178,14 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) m_songMessage.ReadFixedLineLength(commentChunk, commentChunk.BytesLeft(), 40, 0); } } - + m_modFormat.madeWithTracker = U_("ProTracker ") + version; } m_SongFlags.set(SONG_PT_MODE); m_playBehaviour.set(kMODIgnorePanning); m_playBehaviour.set(kMODOneShotLoops); m_playBehaviour.set(kMODSampleSwap); - + return ok; } @@ -2290,6 +2289,7 @@ bool CSoundFile::SaveMod(std::ostream &f) const mpt::IO::Write(f, modMagic); // Write patterns + bool invalidInstruments = false; std::vector events; for(PATTERNINDEX pat = 0; pat < writePatterns; pat++) { @@ -2314,7 +2314,7 @@ bool CSoundFile::SaveMod(std::ostream &f) const events.resize(writeChannels * 4); size_t eventByte = 0; - for(CHANNELINDEX chn = 0; chn < writeChannels; chn++) + for(CHANNELINDEX chn = 0; chn < writeChannels; chn++, eventByte += 4) { ModCommand &m = rowBase[chn]; uint8 command = m.command, param = m.param; @@ -2334,17 +2334,24 @@ bool CSoundFile::SaveMod(std::ostream &f) const period = ProTrackerPeriodTable[m.note - 24 - NOTE_MIN]; } - uint8 instr = (m.instr <= 31) ? m.instr : 0; + const uint8 instr = (m.instr > 31) ? 0 : m.instr; + if(m.instr > 31) + invalidInstruments = true; - events[eventByte++] = ((period >> 8) & 0x0F) | (instr & 0x10); - events[eventByte++] = period & 0xFF; - events[eventByte++] = ((instr & 0x0F) << 4) | (command & 0x0F); - events[eventByte++] = param; + events[eventByte + 0] = ((period >> 8) & 0x0F) | (instr & 0x10); + events[eventByte + 1] = period & 0xFF; + events[eventByte + 2] = ((instr & 0x0F) << 4) | (command & 0x0F); + events[eventByte + 3] = param; } - mpt::IO::WriteRaw(f, mpt::as_span(events.data(), eventByte)); + mpt::IO::WriteRaw(f, mpt::as_span(events)); } } + if(invalidInstruments) + { + AddToLog("Warning: This track references sample slots higher than 31. Such samples cannot be saved in the MOD format, and thus the notes will not sound correct. Use the Cleanup tool to rearrange and remove unused samples."); + } + //Check for unsaved patterns for(PATTERNINDEX pat = writePatterns; pat < Patterns.Size(); pat++) { diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp index e256cb153..bdd6b73d8 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Load_mt2.cpp @@ -1156,7 +1156,7 @@ bool CSoundFile::ReadMT2(FileReader &file, ModLoadingFlags loadFlags) } SetSamplePath(i + 1, mpt::PathString::FromLocaleSilent(filename)); #elif !defined(LIBOPENMPT_BUILD_TEST) - AddToLog(LogWarning, mpt::format(U_("Loading external sample %1 ('%2') failed: External samples are not supported."))(i, mpt::ToUnicode(GetCharsetFile(), filename))); + AddToLog(LogWarning, mpt::format(U_("Loading external sample %1 ('%2') failed: External samples are not supported."))(i + 1, mpt::ToUnicode(GetCharsetFile(), filename))); #endif // MPT_EXTERNAL_SAMPLES } } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp index 2aeed18c5..66ae13d44 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/ModChannel.cpp @@ -122,9 +122,9 @@ ModCommand::NOTE ModChannel::GetPluginNote(bool realNoteMapping) const // If an arpeggio is playing, this definitely the last playing note, which may be different from the arpeggio base note stored in nNote. return nArpeggioLastNote; } - ModCommand::NOTE plugNote = nNote; + ModCommand::NOTE plugNote = mpt::saturate_cast(nNote - nTranspose); // Caution: When in compatible mode, ModChannel::nNote stores the "real" note, not the mapped note! - if(realNoteMapping && pModInstrument != nullptr && plugNote >= NOTE_MIN && plugNote < (MPT_ARRAY_COUNT(pModInstrument->NoteMap) + NOTE_MIN)) + if(realNoteMapping && pModInstrument != nullptr && plugNote >= NOTE_MIN && plugNote < (mpt::size(pModInstrument->NoteMap) + NOTE_MIN)) { plugNote = pModInstrument->NoteMap[plugNote - NOTE_MIN]; } diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp index 2da930ac0..3252d3ca0 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Snd_fx.cpp @@ -25,6 +25,7 @@ #include "modsmp_ctrl.h" // For updating the loop wraparound data with the invert loop effect #include "plugins/PlugInterface.h" #include "OPL.h" +#include "MIDIEvents.h" OPENMPT_NAMESPACE_BEGIN @@ -83,7 +84,9 @@ public: void Reset() { +#ifndef NO_PLUGINS plugParams.clear(); +#endif elapsedTime = 0.0; state->m_lTotalSampleCount = 0; state->m_nMusicSpeed = sndFile.m_nDefaultSpeed; @@ -2025,7 +2028,7 @@ void CSoundFile::NoteChange(ModChannel &chn, int note, bool bPorta, bool bResetE if((chn.nCutOff < 0x7F || m_playBehaviour[kITFilterBehaviour]) && useFilter) { int cutoff = SetupChannelFilter(chn, true); - if(cutoff >= 0 && chn.dwFlags[CHN_ADLIB] && m_opl) + if(cutoff >= 0 && chn.dwFlags[CHN_ADLIB] && m_opl && channelHint != CHANNELINDEX_INVALID) m_opl->Volume(channelHint, chn.nCutOff / 2u, true); } } @@ -2635,7 +2638,7 @@ bool CSoundFile::ProcessEffects() { note = NOTE_NONE; } - } else if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetNumInstruments() != 0 && ModCommand::IsNoteOrEmpty(static_cast(note))) + } else if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT | MOD_TYPE_J2B)) && GetNumInstruments() != 0 && ModCommand::IsNoteOrEmpty(static_cast(note))) { // IT compatibility: Invalid instrument numbers do nothing, but they are remembered for upcoming notes and do not trigger a note in that case. // Test case: InstrumentNumberChange.it @@ -5454,7 +5457,7 @@ void CSoundFile::RetrigNote(CHANNELINDEX nChn, int param, int offset) bool fading = chn.dwFlags[CHN_NOTEFADE]; // IT compatibility: Really weird combination of envelopes and retrigger (see Storlek's q.it testcase) // Test case: retrig.it - NoteChange(chn, note, m_playBehaviour[kITRetrigger], resetEnv); + NoteChange(chn, note, m_playBehaviour[kITRetrigger], resetEnv, false, nChn); // XM compatibility: Prevent NoteChange from resetting the fade flag in case an instrument number + note-off is present. // Test case: RetrigFade.xm if(fading && GetType() == MOD_TYPE_XM) diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h index e3f5f9568..5b55043f7 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndfile.h @@ -64,9 +64,9 @@ OPENMPT_NAMESPACE_BEGIN // MODULAR ModInstrument FIELD ACCESS : body content in InstrumentExtensions.cpp // ----------------------------------------------------------------------------- #ifndef MODPLUG_NO_FILESAVE -extern void WriteInstrumentHeaderStructOrField(ModInstrument * input, std::ostream &file, uint32 only_this_code = -1 /* -1 for all */, uint16 fixedsize = 0); +void WriteInstrumentHeaderStructOrField(ModInstrument * input, std::ostream &file, uint32 only_this_code = -1 /* -1 for all */, uint16 fixedsize = 0); #endif // !MODPLUG_NO_FILESAVE -extern bool ReadInstrumentHeaderField(ModInstrument * input, uint32 fcode, uint16 fsize, FileReader &file); +bool ReadInstrumentHeaderField(ModInstrument * input, uint32 fcode, uint16 fsize, FileReader &file); // -------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------- diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp index 7f51ccf30..603e923e9 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Sndmix.cpp @@ -1817,13 +1817,13 @@ void CSoundFile::ProcessSampleAutoVibrato(ModChannel &chn, int &period, Tuning:: default: if(GetType() != MOD_TYPE_MT2) { - vdelta = ft2VibratoTable[chn.nAutoVibPos & 0xFF]; + vdelta = -ITSinusTable[chn.nAutoVibPos & 0xFF]; } else { // Fix flat-sounding pads in "another worlds" by Eternal Engine. // Vibrato starts at the maximum amplitude of the sine wave // and the vibrato frequency never decreases below the original note's frequency. - vdelta = (ft2VibratoTable[(chn.nAutoVibPos + 192) & 0xFF] + 64) / 2; + vdelta = (-ITSinusTable[(chn.nAutoVibPos + 192) & 0xFF] + 64) / 2; } } int n = (vdelta * chn.nAutoVibDepth) / 256; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.cpp index bd4fa2bb7..3a701b20f 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.cpp @@ -476,28 +476,6 @@ const uint32 XMLinearTable[768] = }; -const int8 ft2VibratoTable[256] = -{ - 0,-2,-3,-5,-6,-8,-9,-11,-12,-14,-16,-17,-19,-20,-22,-23, - -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42, - -43,-44,-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56, - -56,-57,-58,-59,-59,-60,-60,-61,-61,-62,-62,-62,-63,-63, - -63,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-64,-63,-63, - -63,-62,-62,-62,-61,-61,-60,-60,-59,-59,-58,-57,-56,-56, - -55,-54,-53,-52,-51,-50,-49,-48,-47,-46,-45,-44,-43,-42, - -41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,-24,-23, - -22,-20,-19,-17,-16,-14,-12,-11,-9,-8,-6,-5,-3,-2,0, - 2,3,5,6,8,9,11,12,14,16,17,19,20,22,23,24,26,27,29,30, - 32,33,34,36,37,38,39,41,42,43,44,45,46,47,48,49,50,51, - 52,53,54,55,56,56,57,58,59,59,60,60,61,61,62,62,62,63, - 63,63,64,64,64,64,64,64,64,64,64,64,64,63,63,63,62,62, - 62,61,61,60,60,59,59,58,57,56,56,55,54,53,52,51,50,49, - 48,47,46,45,44,43,42,41,39,38,37,36,34,33,32,30,29,27, - 26,24,23,22,20,19,17,16,14,12,11,9,8,6,5,3,2 -}; - - - // round(65536 * 2**(n/768)) // 768 = 64 extra-fine finetune steps for 12 notes // Table content is in 16.16 format @@ -782,7 +760,6 @@ void CResampler::InitFloatmixerTables() void CResampler::InitializeTablesFromScratch(bool force) { - bool initParameterIndependentTables = false; if(force) { diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.h b/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.h index 092d7ac8d..0e4b045d5 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/Tables.h @@ -31,7 +31,6 @@ extern const int8 retrigTable1[16]; extern const int8 retrigTable2[16]; extern const uint16 XMPeriodTable[104]; extern const uint32 XMLinearTable[768]; -extern const int8 ft2VibratoTable[256]; extern const uint32 FineLinearSlideUpTable[16]; extern const uint32 FineLinearSlideDownTable[16]; extern const uint32 LinearSlideUpTable[256]; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/modcommand.cpp b/Frameworks/OpenMPT/OpenMPT/soundlib/modcommand.cpp index 4d11e0091..1c9217d54 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/modcommand.cpp +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/modcommand.cpp @@ -179,7 +179,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd param = 0x91; } else { - param = std::min(param << 1, 0xFF); + param = mpt::saturate_cast(param * 2u); } } } // End if(command == CMD_PANNING8) @@ -515,7 +515,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd param = (param & 0xF0) | std::min((param & 0x0F) * 2u, 15); break; case CMD_GLOBALVOLUME: - param = std::min(0x80, param * 2u); + param = std::min(0x40, param) * 2u; break; } } // End if(oldTypeIsIT_MPT && newTypeIsXM) @@ -776,7 +776,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd if(newTypeIsIT_MPT) { // Convert some commands which behave differently or don't exist - if(command == CMD_NONE) switch(volcmd) + if(!oldTypeIsIT_MPT && command == CMD_NONE) switch(volcmd) { case VOLCMD_PANSLIDELEFT: command = CMD_PANNINGSLIDE; diff --git a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginMixBuffer.h b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginMixBuffer.h index e7a62dc74..4e18524c9 100644 --- a/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginMixBuffer.h +++ b/Frameworks/OpenMPT/OpenMPT/soundlib/plugins/PluginMixBuffer.h @@ -12,6 +12,9 @@ #include "BuildSettings.h" +#include "../../common/mptAlloc.h" + + OPENMPT_NAMESPACE_BEGIN @@ -25,7 +28,11 @@ protected: std::vector inputs; // Pointers to input buffers std::vector outputs; // Pointers to output buffers +#if defined(MPT_ENABLE_ALIGNED_ALLOC) mpt::aligned_buffer alignedBuffer; // Aligned buffer pointed into +#else + std::vector alignedBuffer; +#endif // Return pointer to an aligned buffer const buffer_t *GetBuffer(size_t index) const @@ -56,7 +63,11 @@ public: outputs.resize(numOutputs); // Create inputs + outputs buffers - alignedBuffer.destructive_resize(bufferSize * (numInputs + numOutputs)); + #if defined(MPT_ENABLE_ALIGNED_ALLOC) + alignedBuffer.destructive_resize(bufferSize * (numInputs + numOutputs)); + #else + alignedBuffer.resize(bufferSize * (numInputs + numOutputs)); + #endif } MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e) { @@ -65,7 +76,11 @@ public: inputs.shrink_to_fit(); outputs.clear(); outputs.shrink_to_fit(); - alignedBuffer.destructive_resize(0); + #if defined(MPT_ENABLE_ALIGNED_ALLOC) + alignedBuffer.destructive_resize(0); + #else + alignedBuffer.resize(0); + #endif return false; } diff --git a/Frameworks/OpenMPT/OpenMPT/test/test.cpp b/Frameworks/OpenMPT/OpenMPT/test/test.cpp index 540a2000e..39b2c2da3 100644 --- a/Frameworks/OpenMPT/OpenMPT/test/test.cpp +++ b/Frameworks/OpenMPT/OpenMPT/test/test.cpp @@ -32,6 +32,7 @@ #include "../soundlib/ITCompression.h" #include "../soundlib/tuningcollection.h" #include "../soundlib/tuning.h" +#include "../soundlib/Dither.h" #ifdef MODPLUG_TRACKER #include "../mptrack/Mptrack.h" #include "../mptrack/Moddoc.h" @@ -1494,9 +1495,10 @@ static MPT_NOINLINE void TestMisc2() { VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull).ToUString(), U_("2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32")); #if defined(MODPLUG_TRACKER) || !defined(NO_DMO) - VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), "2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"_uuid); - VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToGUID(L"{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}"))); - VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToCLSID(L"{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}"))); + constexpr mpt::UUID uuid_tmp = "2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"_uuid; + VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), uuid_tmp); + VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToGUID(_T("{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}")))); + VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToCLSID(_T("{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}")))); #endif #if defined(MODPLUG_TRACKER) || !defined(NO_DMO) @@ -4714,6 +4716,82 @@ static MPT_NOINLINE void TestSampleConversion() VERIFY_EQUAL_NONCONT(signed8[3], 0); } + // Dither + { + std::vector buffer(64); + Dither dither(mpt::global_random_device()); + dither.SetMode(DitherModPlug); + dither.Process(buffer.data(), 64, 1, 16); + std::vector expected = { + 727, + -557, + -552, + -727, + 439, + 405, + 703, + -337, + 235, + -776, + -458, + 905, + -110, + 158, + 374, + -362, + 283, + 306, + 710, + 304, + -608, + 536, + -501, + -593, + -349, + 812, + 916, + 53, + -953, + 881, + -236, + -20, + -623, + -895, + -302, + -415, + 899, + -948, + -766, + -186, + -390, + -169, + 253, + -622, + -769, + -1001, + 1019, + 787, + -239, + 718, + -423, + 988, + -91, + 763, + -933, + -510, + 484, + 794, + -340, + 552, + 866, + -608, + 35, + 395}; + for(std::size_t i = 0; i < 64; ++i) + { + VERIFY_EQUAL_QUIET_NONCONT(buffer[i], expected[i]); + } + } }