Updated libopenmpt to version 0.4.9

CQTexperiment
Christopher Snowhill 2019-10-24 17:33:28 -07:00
parent 2ad9584fb2
commit dbaf952429
42 changed files with 623 additions and 275 deletions

View File

@ -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/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/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/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/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/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 svn export ./build/vs bin/dist-zip/libopenmpt-$(DIST_LIBOPENMPT_VERSION)/build/vs --native-eol CRLF

View File

@ -1,4 +1,4 @@
MPT_SVNVERSION=11626 MPT_SVNVERSION=12139
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.5 MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.9
MPT_SVNDATE=2019-05-27T06:47:50.022790Z MPT_SVNDATE=2019-10-02T14:33:59.345896Z

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#define OPENMPT_VERSION_SVNVERSION "11626" #define OPENMPT_VERSION_SVNVERSION "12139"
#define OPENMPT_VERSION_REVISION 11626 #define OPENMPT_VERSION_REVISION 12139
#define OPENMPT_VERSION_DIRTY 0 #define OPENMPT_VERSION_DIRTY 0
#define OPENMPT_VERSION_MIXEDREVISIONS 0 #define OPENMPT_VERSION_MIXEDREVISIONS 0
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.5" #define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.4.9"
#define OPENMPT_VERSION_DATE "2019-05-27T06:47:50.022790Z" #define OPENMPT_VERSION_DATE "2019-10-02T14:33:59.345896Z"
#define OPENMPT_VERSION_IS_PACKAGE 1 #define OPENMPT_VERSION_IS_PACKAGE 1

View File

@ -578,6 +578,10 @@
#define NO_DMO #define NO_DMO
#endif #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) #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 <vector>
#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 // third-party library configuration
#if defined(MODPLUG_TRACKER) #if defined(MODPLUG_TRACKER)

View File

@ -58,7 +58,9 @@
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
#define MPT_COMPILER_MSVC 1 #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) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,1)
#elif (_MSC_VER >= 1920) #elif (_MSC_VER >= 1920)
#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,0) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2019,0)
@ -230,6 +232,8 @@
//#elif TARGET_OS_MAC //#elif TARGET_OS_MAC
//#else //#else
//#endif //#endif
#elif defined(__HAIKU__)
#define MPT_OS_HAIKU 1
#elif defined(__ANDROID__) || defined(ANDROID) #elif defined(__ANDROID__) || defined(ANDROID)
#define MPT_OS_ANDROID 1 #define MPT_OS_ANDROID 1
#elif defined(__linux__) #elif defined(__linux__)
@ -263,6 +267,9 @@
#ifndef MPT_OS_MACOSX_OR_IOS #ifndef MPT_OS_MACOSX_OR_IOS
#define MPT_OS_MACOSX_OR_IOS 0 #define MPT_OS_MACOSX_OR_IOS 0
#endif #endif
#ifndef MPT_OS_HAIKU
#define MPT_OS_HAIKU 0
#endif
#ifndef MPT_OS_ANDROID #ifndef MPT_OS_ANDROID
#define MPT_OS_ANDROID 0 #define MPT_OS_ANDROID 0
#endif #endif

View File

@ -30,6 +30,10 @@ OPENMPT_NAMESPACE_BEGIN
#if defined(MPT_ENABLE_ALIGNED_ALLOC)
namespace mpt 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) 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; std::size_t space = count * size;
void* mem = std::aligned_alloc(alignment, space); void* mem = std::aligned_alloc(alignment, space);
if(!mem) 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(); MPT_EXCEPTION_THROW_OUT_OF_MEMORY();
} }
return aligned_raw_memory{mem, mem}; 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; std::size_t space = count * size;
void* mem = _aligned_malloc(space, alignment); void* mem = _aligned_malloc(space, alignment);
if(!mem) 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) 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); std::free(raw.mem);
#elif MPT_COMPILER_MSVC #elif MPT_COMPILER_MSVC || (defined(__clang__) && defined(_MSC_VER))
_aligned_free(raw.mem); _aligned_free(raw.mem);
#else #else
std::free(raw.mem); std::free(raw.mem);
@ -118,4 +122,8 @@ void aligned_free(aligned_raw_memory raw)
#endif // MPT_ENABLE_ALIGNED_ALLOC
OPENMPT_NAMESPACE_END OPENMPT_NAMESPACE_END

View File

@ -95,6 +95,10 @@ std::unique_ptr<T> make_unique(Args&&... args)
#if defined(MPT_ENABLE_ALIGNED_ALLOC)
namespace mpt namespace mpt
{ {
@ -259,4 +263,8 @@ public:
#endif // MPT_ENABLE_ALIGNED_ALLOC
OPENMPT_NAMESPACE_END OPENMPT_NAMESPACE_END

View File

@ -515,7 +515,8 @@ InputFile::ContentsRef InputFile::Get()
return result; return result;
} }
result.first.data = m_File.Lock(); 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; result.second = &m_Filename;
return result; return result;
} }

View File

@ -74,16 +74,16 @@ bool Flush(std::ostream & f);
template <typename Tfile> class WriteBuffer; template <typename Tfile> class WriteBuffer;
template <typename Tfile> bool IsValid(WriteBuffer<Tfile> & f) { return IsValid(f.file()); } template <typename Tfile> bool IsValid(WriteBuffer<Tfile> & f) { return IsValid(f.file()); }
template <typename Tfile> IO::Offset TellRead(WriteBuffer<Tfile> & f) { return TellRead(f.file()); } template <typename Tfile> IO::Offset TellRead(WriteBuffer<Tfile> & f) { f.FlushLocal(); return TellRead(f.file()); }
template <typename Tfile> IO::Offset TellWrite(WriteBuffer<Tfile> & f) { return TellWrite(f.file()); } template <typename Tfile> IO::Offset TellWrite(WriteBuffer<Tfile> & f) { return TellWrite(f.file()) + f.GetCurrentSize(); }
template <typename Tfile> bool SeekBegin(WriteBuffer<Tfile> & f) { return SeekBegin(f.file()); } template <typename Tfile> bool SeekBegin(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekBegin(f.file()); }
template <typename Tfile> bool SeekEnd(WriteBuffer<Tfile> & f) { return SeekEnd(f.file()); } template <typename Tfile> bool SeekEnd(WriteBuffer<Tfile> & f) { f.FlushLocal(); return SeekEnd(f.file()); }
template <typename Tfile> bool SeekAbsolute(WriteBuffer<Tfile> & f, IO::Offset pos) { return SeekAbsolute(f.file(), pos); } template <typename Tfile> bool SeekAbsolute(WriteBuffer<Tfile> & f, IO::Offset pos) { return f.FlushLocal(); SeekAbsolute(f.file(), pos); }
template <typename Tfile> bool SeekRelative(WriteBuffer<Tfile> & f, IO::Offset off) { return SeekRelative(f.file(), off); } template <typename Tfile> bool SeekRelative(WriteBuffer<Tfile> & f, IO::Offset off) { return f.FlushLocal(); SeekRelative(f.file(), off); }
template <typename Tfile> IO::Offset ReadRawImpl(WriteBuffer<Tfile> & f, mpt::byte * data, std::size_t size) { return ReadRawImpl(f.file(), data, size); } template <typename Tfile> IO::Offset ReadRawImpl(WriteBuffer<Tfile> & f, mpt::byte * data, std::size_t size) { f.FlushLocal(); return ReadRawImpl(f.file(), data, size); }
template <typename Tfile> bool WriteRawImpl(WriteBuffer<Tfile> & f, const mpt::byte * data, std::size_t size) { return f.Write(mpt::as_span(data, size)); } template <typename Tfile> bool WriteRawImpl(WriteBuffer<Tfile> & f, const mpt::byte * data, std::size_t size) { return f.Write(mpt::as_span(data, size)); }
template <typename Tfile> bool IsEof(WriteBuffer<Tfile> & f) { return IsEof(f.file()); } template <typename Tfile> bool IsEof(WriteBuffer<Tfile> & f) { f.FlushLocal(); return IsEof(f.file()); }
template <typename Tfile> bool Flush(WriteBuffer<Tfile> & f) { return Flush(f.file()); } template <typename Tfile> bool Flush(WriteBuffer<Tfile> & f) { f.FlushLocal(); return Flush(f.file()); }
@ -627,6 +627,10 @@ public:
{ {
return size == buffer.size(); return size == buffer.size();
} }
inline std::size_t GetCurrentSize() const
{
return size;
}
inline bool Write(mpt::const_byte_span data) inline bool Write(mpt::const_byte_span data)
{ {
bool result = true; bool result = true;

View File

@ -17,7 +17,20 @@
#endif #endif
#if MPT_FORMAT_CXX17_INT #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 <charconv> #include <charconv>
#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 #endif // MPT_FORMAT_CXX17_INT
#include <iomanip> #include <iomanip>
#include <locale> #include <locale>

View File

@ -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. MPT_DEPRECATED std::string ToString(const mpt::ustring & x); // Unknown encoding.
#endif #endif
#if defined(_MFC_VER) #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); MPT_DEPRECATED std::string ToString(const CString & x);
#endif #endif
std::string ToString(const bool & x); std::string ToString(const bool & x);

View File

@ -20,8 +20,8 @@ OPENMPT_NAMESPACE_BEGIN
//Version definitions. The only thing that needs to be changed when changing version number. //Version definitions. The only thing that needs to be changed when changing version number.
#define VER_MAJORMAJOR 1 #define VER_MAJORMAJOR 1
#define VER_MAJOR 28 #define VER_MAJOR 28
#define VER_MINOR 05 #define VER_MINOR 07
#define VER_MINORMINOR 00 #define VER_MINORMINOR 04
//Numerical value of the version. //Numerical value of the version.
#define MPT_VERSION_CURRENT MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR) #define MPT_VERSION_CURRENT MAKE_VERSION_NUMERIC(VER_MAJORMAJOR,VER_MAJOR,VER_MINOR,VER_MINORMINOR)

View File

@ -20,7 +20,22 @@
#include <libopenmpt/libopenmpt.hpp> #include <libopenmpt/libopenmpt.hpp>
#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 <portaudiocpp/PortAudioCpp.hxx> #include <portaudiocpp/PortAudioCpp.hxx>
#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( _WIN32 ) || defined( WIN32 ) ) && ( defined( _UNICODE ) || defined( UNICODE ) )
#if defined( __GNUC__ ) #if defined( __GNUC__ )

View File

@ -1,4 +1,4 @@
minimp3 library from https://github.com/lieff/minimp3 minimp3 library from https://github.com/lieff/minimp3
commit e9df0760e94044caded36a55d70ab4152134adc5 (2018-12-23) commit 977514a6dfc4960d819a103f43b358e58ac6c28f (2019-07-24)
The following changes have been made: The following changes have been made:
* minimp3.c has been added * minimp3.c has been added

View File

@ -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++]; int sfb_cnt = gr_info->region_count[ireg++];
const int16_t *codebook = tabs + tabindex[tab_num]; const int16_t *codebook = tabs + tabindex[tab_num];
int linbits = g_linbits[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 do
{ {
int j, w = 5; np = *sfb++ / 2;
int leaf = codebook[PEEK_BITS(w)]; pairs_to_decode = MINIMP3_MIN(big_val_cnt, np);
while (leaf < 0) one = *scf++;
do
{ {
FLUSH_BITS(w); int j, w = 5;
w = leaf & 7; int leaf = codebook[PEEK_BITS(w)];
leaf = codebook[PEEK_BITS(w) - (leaf >> 3)]; while (leaf < 0)
}
FLUSH_BITS(leaf >> 8);
for (j = 0; j < 2; j++, dst++, leaf >>= 4)
{
int lsb = leaf & 0x0F;
if (lsb == 15 && linbits)
{ {
lsb += PEEK_BITS(linbits); FLUSH_BITS(w);
FLUSH_BITS(linbits); w = leaf & 7;
CHECK_BITS; leaf = codebook[PEEK_BITS(w) - (leaf >> 3)];
*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); FLUSH_BITS(leaf >> 8);
}
CHECK_BITS; for (j = 0; j < 2; j++, dst++, leaf >>= 4)
} while (--pairs_to_decode); {
} while ((big_val_cnt -= np) > 0 && --sfb_cnt >= 0); 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) for (np = 1 - big_val_cnt;; dst += 4)

View File

@ -1,6 +1,6 @@
miniz DEFLATE implementation. miniz DEFLATE implementation.
https://github.com/richgel999/miniz https://github.com/richgel999/miniz
2.0.8 2.1.0
Modifications for OpenMPT: Modifications for OpenMPT:
* #define MINIZ_NO_STDIO has been set because OpenMPT does not need stdio * #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 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 *') * Warning `warning: cast from 'const mz_uint8 *' (aka 'const unsigned char *')
to 'const mz_uint32 *' (aka 'const unsigned int *') increases required to 'const mz_uint32 *' (aka 'const unsigned int *') increases required
alignment from 1 to 4 [-Wcast-align]` has been fixed. 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 have beeen fixed
* Missing #ifndef MINIZ_NO_STDIO has been added to miniz.h. * Missing #ifndef MINIZ_NO_STDIO has been added to miniz.h.
No further changes have been made. No further changes have been made.

View File

@ -397,6 +397,32 @@ int mz_inflateInit(mz_streamp pStream)
return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); 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) int mz_inflate(mz_streamp pStream, int flush)
{ {
inflate_state *pState; inflate_state *pState;
@ -1340,13 +1366,13 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush)
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
#ifdef MINIZ_UNALIGNED_USE_MEMCPY #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; mz_uint16 ret;
memcpy(&ret, p, sizeof(mz_uint16)); memcpy(&ret, p, sizeof(mz_uint16));
return ret; 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; mz_uint16 ret;
memcpy(&ret, p, sizeof(mz_uint16)); 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 */ #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN #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) 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. */ /* 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_uint cur_match_dist, cur_match_len = 1;
mz_uint8 *pCur_dict = d->m_dict + cur_pos; 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 hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
mz_uint probe_pos = d->m_hash[hash]; mz_uint probe_pos = d->m_hash[hash];
d->m_hash[hash] = (mz_uint16)lookahead_pos; 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 *p = (const mz_uint16 *)pCur_dict;
const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); 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--; cur_match_dist--;
pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); 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; *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
#endif
pLZ_code_buf += 3; pLZ_code_buf += 3;
*pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); *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); 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 */ /* 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 */ /* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
/* structure size and allocation mechanism. */ /* structure size and allocation mechanism. */
@ -2159,6 +2200,7 @@ void tdefl_compressor_free(tdefl_compressor *pComp)
{ {
MZ_FREE(pComp); MZ_FREE(pComp);
} }
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #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); const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
do 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)[0] = ((const mz_uint32 *)pSrc)[0];
((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
#endif
pOut_buf_cur += 8; pOut_buf_cur += 8;
} while ((pSrc += 8) < pSrc_end); } while ((pSrc += 8) < pSrc_end);
if ((counter &= 7) < 3) 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; return result;
} }
#ifndef MINIZ_NO_MALLOC
#if 0 // OpenMPT #if 0 // OpenMPT
tinfl_decompressor *tinfl_decompressor_alloc() tinfl_decompressor *tinfl_decompressor_alloc()
#else // OpenMPT #else // OpenMPT
@ -2901,6 +2948,7 @@ void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
{ {
MZ_FREE(pDecomp); MZ_FREE(pDecomp);
} }
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -2969,8 +3017,8 @@ static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
#define MZ_FWRITE fwrite #define MZ_FWRITE fwrite
#define MZ_FTELL64 _ftelli64 #define MZ_FTELL64 _ftelli64
#define MZ_FSEEK64 _fseeki64 #define MZ_FSEEK64 _fseeki64
#define MZ_FILE_STAT_STRUCT _stat #define MZ_FILE_STAT_STRUCT _stat64
#define MZ_FILE_STAT _stat #define MZ_FILE_STAT _stat64
#define MZ_FFLUSH fflush #define MZ_FFLUSH fflush
#define MZ_FREOPEN mz_freopen #define MZ_FREOPEN mz_freopen
#define MZ_DELETE_FILE remove #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_FFLUSH fflush
#define MZ_FREOPEN(f, m, s) freopen(f, m, s) #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
#define MZ_DELETE_FILE remove #define MZ_DELETE_FILE remove
#elif defined(__GNUC__) && _LARGEFILE64_SOURCE #elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
#ifndef MINIZ_NO_TIME #ifndef MINIZ_NO_TIME
#include <utime.h> #include <utime.h>
#endif #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; size_t orig_size = pArray->m_size;
if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
return MZ_FALSE; 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; 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) 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 do
{ {
mz_uint32 field_id; mz_uint32 field_id;
mz_uint32 field_data_size; mz_uint32 field_data_size;
if (extra_size_remaining < (sizeof(mz_uint16) * 2)) if (extra_size_remaining < (sizeof(mz_uint16) * 2))
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); {
MZ_FREE(buf);
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
}
field_id = MZ_READ_LE16(pExtra_data); field_id = MZ_READ_LE16(pExtra_data);
field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16)); field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining) if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED); {
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) 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; pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size; extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
} while (extra_size_remaining); } 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)) 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. */ /* 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? */ /* Zip is in memory....or requires reading from a file? */
if (pState->pZip->m_pState->m_pMem) 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) 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); 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); 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)) || 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 == '/') if (*pArchive_name == '/')
return MZ_FALSE; return MZ_FALSE;
while (*pArchive_name) /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
{
if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
return MZ_FALSE;
pArchive_name++;
}
return MZ_TRUE; 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); (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); 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)) 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)) if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); 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); 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)) 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); (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, 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)) user_extra_data_central, user_extra_data_central_len))
return MZ_FALSE; 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; return MZ_TRUE;
} }
#ifndef MINIZ_NO_STDIO 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,
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) 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; 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_uint32 extra_size = 0;
mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE]; mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
mz_zip_internal_state *pState; mz_zip_internal_state *pState;
mz_uint64 file_ofs = 0;
if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME)) if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8; gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
@ -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); (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); 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)) 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)) if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); 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); 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)) 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) while (uncomp_remaining)
{ {
mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, 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); pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED); 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_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
uncomp_remaining -= n; uncomp_remaining -= n;
cur_archive_file_ofs += 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_status status;
tdefl_flush flush = TDEFL_NO_FLUSH; 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); mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
break; break;
} }
file_ofs += in_buf_size;
uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
uncomp_remaining -= 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); (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, 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)) user_extra_data_central, user_extra_data_central_len))
return MZ_FALSE; 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; 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_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; MZ_FILE *pSrc_file = NULL;

View File

@ -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. See "unlicense" statement at the end of this file.
Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013 Rich Geldreich <richgel99@gmail.com>, 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 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: zlib replacement in many apps:
The z_stream struct, optional memory allocation callbacks The z_stream struct, optional memory allocation callbacks
deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound
inflateInit/inflateInit2/inflate/inflateEnd inflateInit/inflateInit2/inflate/inflateReset/inflateEnd
compress, compress2, compressBound, uncompress compress, compress2, compressBound, uncompress
CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. 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. Supports raw deflate streams or standard zlib streams with adler-32 checking.
@ -179,16 +179,20 @@
#endif // OpenMPT #endif // OpenMPT
#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 #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. */ /* 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 #if 0 // OpenMPT
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
#define MINIZ_UNALIGNED_USE_MEMCPY
#else // OpenMPT #else // OpenMPT
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 // OpenMPT #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 // OpenMPT
#endif // OpenMPT #endif // OpenMPT
#else #else
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0 #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
#endif #endif
#endif
#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) #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). */ /* 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 MZ_DEFAULT_COMPRESSION = -1
}; };
#define MZ_VERSION "10.0.3" #define MZ_VERSION "10.1.0"
#define MZ_VERNUM 0xA030 #define MZ_VERNUM 0xA100
#define MZ_VER_MAJOR 10 #define MZ_VER_MAJOR 10
#define MZ_VER_MINOR 0 #define MZ_VER_MINOR 1
#define MZ_VER_REVISION 3 #define MZ_VER_REVISION 0
#define MZ_VER_SUBREVISION 0 #define MZ_VER_SUBREVISION 0
#ifndef MINIZ_NO_ZLIB_APIS #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). */ /* 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); 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. */ /* 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: */ /* 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. */ /* 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 compressBound mz_compressBound
#define inflateInit mz_inflateInit #define inflateInit mz_inflateInit
#define inflateInit2 mz_inflateInit2 #define inflateInit2 mz_inflateInit2
#define inflateReset mz_inflateReset
#define inflate mz_inflate #define inflate mz_inflate
#define inflateEnd mz_inflateEnd #define inflateEnd mz_inflateEnd
#define uncompress mz_uncompress #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 */ /* 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); 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 */ /* Allocate the tdefl_compressor structure in C so that */
/* non-C language bindings to tdefl_ API don't need to worry about */ /* non-C language bindings to tdefl_ API don't need to worry about */
/* structure size and allocation mechanism. */ /* structure size and allocation mechanism. */
#if 0 // OpenMPT tdefl_compressor *tdefl_compressor_alloc(void);
tdefl_compressor *tdefl_compressor_alloc();
#else // OpenMPT
tdefl_compressor *tdefl_compressor_alloc(void); // OpenMPT
#endif // OpenMPT
void tdefl_compressor_free(tdefl_compressor *pComp); void tdefl_compressor_free(tdefl_compressor *pComp);
#endif
#ifdef __cplusplus #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; struct tinfl_decompressor_tag;
typedef struct tinfl_decompressor_tag tinfl_decompressor; typedef struct tinfl_decompressor_tag tinfl_decompressor;
#ifndef MINIZ_NO_MALLOC
/* Allocate the tinfl_decompressor structure in C so that */ /* Allocate the tinfl_decompressor structure in C so that */
/* non-C language bindings to tinfl_ API don't need to worry about */ /* non-C language bindings to tinfl_ API don't need to worry about */
/* structure size and allocation mechanism. */ /* structure size and allocation mechanism. */
tinfl_decompressor *tinfl_decompressor_alloc(void);
#if 0 // OpenMPT
tinfl_decompressor *tinfl_decompressor_alloc();
#else // OpenMPT
tinfl_decompressor *tinfl_decompressor_alloc(void); // OpenMPT
#endif // OpenMPT
void tinfl_decompressor_free(tinfl_decompressor *pDecomp); void tinfl_decompressor_free(tinfl_decompressor *pDecomp);
#endif
/* Max size of LZ dictionary. */ /* Max size of LZ dictionary. */
#define TINFL_LZ_DICT_SIZE 32768 #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, 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); 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 #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. */ /* 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. */ /* 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. */

View File

@ -1,6 +1,6 @@
This folder contains the stb_vorbis library from This folder contains the stb_vorbis library from
https://github.com/nothings/stb/blob/master/stb_vorbis.c v1.16 https://github.com/nothings/stb/blob/master/stb_vorbis.c v1.17
commit 2c2908f50515dcd939f24be261c3ccbcd277bb49 (2019-03-05) commit 130f28df68c3fdbf043c4275260ba1c870495b5b (2019-08-09)
Modifications: Modifications:
* Use of alloca has been replaced with malloc, as alloca is not in C99 and * Use of alloca has been replaced with malloc, as alloca is not in C99 and

View File

@ -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/ // http://nothings.org/stb_vorbis/
// //
// Original version written by Sean Barrett in 2007. // Original version written by Sean Barrett in 2007.
@ -30,9 +30,10 @@
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart // Phillip Bennefall Rohit Thiago Goulart
// manxorist@github saga musix github:infatum // manxorist@github saga musix github:infatum
// Timur Gagiev // Timur Gagiev Maxwell Koo
// //
// Partial history: // Partial history:
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
// 1.16 - 2019-03-04 - fix warnings // 1.16 - 2019-03-04 - fix warnings
// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found // 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
// 1.14 - 2018-02-11 - delete bogus dealloca usage // 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)); int r = (int) floor(exp((float) log((float) entries) / dim));
if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning; if ((int) floor(pow((float) r+1, dim)) <= entries) // (int) cast for MinGW warning;
++r; // floor() to avoid _ftol() when non-CRT ++r; // floor() to avoid _ftol() when non-CRT
assert(pow((float) r+1, dim) > entries); if (pow((float) r+1, dim) <= entries)
assert((int) floor(pow((float) r, dim)) <= entries); // (int),floor() as above return -1;
if ((int) floor(pow((float) r, dim)) > entries)
return -1;
return r; 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; ady -= abs(base) * adx;
if (x1 > n) x1 = n; if (x1 > n) x1 = n;
if (x < x1) { 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) { for (++x; x < x1; ++x) {
err += ady; err += ady;
if (err >= adx) { if (err >= adx) {
@ -2030,7 +2033,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
y += sy; y += sy;
} else } else
y += base; 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; len <<= 1;
if (len == f->blocksize_0) return f->window[0]; if (len == f->blocksize_0) return f->window[0];
if (len == f->blocksize_1) return f->window[1]; if (len == f->blocksize_1) return f->window[1];
assert(0);
return NULL; return NULL;
} }
@ -3463,6 +3465,7 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
if (f->previous_length) { if (f->previous_length) {
int i,j, n = f->previous_length; int i,j, n = f->previous_length;
float *w = get_window(f, n); float *w = get_window(f, n);
if (w == NULL) return 0;
for (i=0; i < f->channels; ++i) { for (i=0; i < f->channels; ++i) {
for (j=0; j < n; ++j) for (j=0; j < n; ++j)
f->channel_buffers[i][left+j] = f->channel_buffers[i][left+j] =
@ -3704,6 +3707,7 @@ static int start_decoder(vorb *f)
while (current_entry < c->entries) { while (current_entry < c->entries) {
int limit = c->entries - current_entry; int limit = c->entries - current_entry;
int n = get_bits(f, ilog(limit)); 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); } if (current_entry + n > (int) c->entries) { return error(f, VORBIS_invalid_setup); }
memset(lengths + current_entry, current_length, n); memset(lengths + current_entry, current_length, n);
current_entry += n; current_entry += n;
@ -3807,7 +3811,9 @@ static int start_decoder(vorb *f)
c->value_bits = get_bits(f, 4)+1; c->value_bits = get_bits(f, 4)+1;
c->sequence_p = get_bits(f,1); c->sequence_p = get_bits(f,1);
if (c->lookup_type == 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 { } else {
c->lookup_values = c->entries * c->dimensions; c->lookup_values = c->entries * c->dimensions;
} }
@ -3943,6 +3949,9 @@ static int start_decoder(vorb *f)
p[j].id = j; p[j].id = j;
} }
qsort(p, g->values, sizeof(p[0]), point_compare); 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) for (j=0; j < g->values; ++j)
g->sorted_order[j] = (uint8) p[j].id; g->sorted_order[j] = (uint8) p[j].id;
// precompute the neighbors // precompute the neighbors
@ -4034,6 +4043,7 @@ static int start_decoder(vorb *f)
max_submaps = m->submaps; max_submaps = m->submaps;
if (get_bits(f,1)) { if (get_bits(f,1)) {
m->coupling_steps = get_bits(f,8)+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) { for (k=0; k < m->coupling_steps; ++k) {
m->chan[k].magnitude = get_bits(f, ilog(f->channels-1)); m->chan[k].magnitude = get_bits(f, ilog(f->channels-1));
m->chan[k].angle = 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 #endif // STB_VORBIS_NO_PULLDATA_API
/* Version history /* 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.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.11 - 2017-07-23 - fix MinGW compilation
1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory

View File

@ -10,8 +10,8 @@ libopenmpt.
Installation Installation
------------ ------------
"in_openmpt.dll" and "openmpt-mpg123.dll" must both be placed into the Winamp "in_openmpt.dll" must be placed into the Winamp "Plugins" directory, and
"Plugins" directory. "openmpt-mpg123.dll" must be placed into the Winamp directory.
See https://lib.openmpt.org/ for documentation, FAQ and other details. See https://lib.openmpt.org/ for documentation, FAQ and other details.

View File

@ -5,6 +5,56 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This For fully detailed change log, please see the source repository directly. This
is just a high-level summary. 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) ### libopenmpt 0.4.5 (2019-05-27)
* [**Sec**] Possible crash during playback due out-of-bounds read in XM and * [**Sec**] Possible crash during playback due out-of-bounds read in XM and

View File

@ -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) LIBOPENMPT_MODPLUG_API unsigned int ModPlug_SampleName(ModPlugFile* file, unsigned int qual, char* buff)
{ {
const char* str; const char* str;
unsigned int retval; char buf[32];
size_t tmpretval;
if(!file) return 0; if(!file) return 0;
str = openmpt_module_get_sample_name(file->mod,qual-1); str = openmpt_module_get_sample_name(file->mod,qual-1);
if(!str){ memset(buf,0,32);
if(buff){ if(str){
*buff = '\0'; strncpy(buf,str,31);
} openmpt_free_string(str);
return 0;
} }
tmpretval = strlen(str);
if(tmpretval>=INT_MAX){
tmpretval = INT_MAX-1;
}
retval = (int)tmpretval;
if(buff){ if(buff){
memcpy(buff,str,retval+1); strncpy(buff,buf,32);
buff[retval] = '\0';
} }
openmpt_free_string(str); return (unsigned int)strlen(buf);
return retval;
} }
LIBOPENMPT_MODPLUG_API unsigned int ModPlug_InstrumentName(ModPlugFile* file, unsigned int qual, char* buff) LIBOPENMPT_MODPLUG_API unsigned int ModPlug_InstrumentName(ModPlugFile* file, unsigned int qual, char* buff)
{ {
const char* str; const char* str;
unsigned int retval; char buf[32];
size_t tmpretval;
if(!file) return 0; if(!file) return 0;
str = openmpt_module_get_instrument_name(file->mod,qual-1); str = openmpt_module_get_instrument_name(file->mod,qual-1);
if(!str){ memset(buf,0,32);
if(buff){ if(str){
*buff = '\0'; strncpy(buf,str,31);
} openmpt_free_string(str);
return 0;
} }
tmpretval = strlen(str);
if(tmpretval>=INT_MAX){
tmpretval = INT_MAX-1;
}
retval = (int)tmpretval;
if(buff){ if(buff){
memcpy(buff,str,retval+1); strncpy(buff,buf,32);
buff[retval] = '\0';
} }
openmpt_free_string(str); return (unsigned int)strlen(buf);
return retval;
} }
LIBOPENMPT_MODPLUG_API ModPlugNote* ModPlug_GetPattern(ModPlugFile* file, int pattern, unsigned int* numrows) LIBOPENMPT_MODPLUG_API ModPlugNote* ModPlug_GetPattern(ModPlugFile* file, int pattern, unsigned int* numrows)

View File

@ -304,9 +304,6 @@ void CSoundFile::SetCurrentOrder( UINT nOrder ) {
UINT CSoundFile::GetSampleName( UINT nSample, LPSTR s ) const { UINT CSoundFile::GetSampleName( UINT nSample, LPSTR s ) const {
mpcpplog(); mpcpplog();
if ( !s ) {
return 0;
}
char buf[32]; char buf[32];
std::memset( buf, 0, 32 ); std::memset( buf, 0, 32 );
if ( mod ) { if ( mod ) {
@ -315,15 +312,14 @@ UINT CSoundFile::GetSampleName( UINT nSample, LPSTR s ) const {
std::strncpy( buf, names[ nSample - 1 ].c_str(), 31 ); std::strncpy( buf, names[ nSample - 1 ].c_str(), 31 );
} }
} }
std::memcpy( s, buf, 32 ); if ( s ) {
std::strncpy( s, buf, 32 );
}
return static_cast<UINT>( std::strlen( buf ) ); return static_cast<UINT>( std::strlen( buf ) );
} }
UINT CSoundFile::GetInstrumentName( UINT nInstr, LPSTR s ) const { UINT CSoundFile::GetInstrumentName( UINT nInstr, LPSTR s ) const {
mpcpplog(); mpcpplog();
if ( !s ) {
return 0;
}
char buf[32]; char buf[32];
std::memset( buf, 0, 32 ); std::memset( buf, 0, 32 );
if ( mod ) { if ( mod ) {
@ -332,7 +328,9 @@ UINT CSoundFile::GetInstrumentName( UINT nInstr, LPSTR s ) const {
std::strncpy( buf, names[ nInstr - 1 ].c_str(), 31 ); std::strncpy( buf, names[ nInstr - 1 ].c_str(), 31 );
} }
} }
std::memcpy( s, buf, 32 ); if ( s ) {
std::strncpy( s, buf, 32 );
}
return static_cast<UINT>( std::strlen( buf ) ); return static_cast<UINT>( std::strlen( buf ) );
} }

View File

@ -19,7 +19,7 @@
/*! \brief libopenmpt minor version number */ /*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 4 #define OPENMPT_API_VERSION_MINOR 4
/*! \brief libopenmpt patch version number */ /*! \brief libopenmpt patch version number */
#define OPENMPT_API_VERSION_PATCH 5 #define OPENMPT_API_VERSION_PATCH 9
/*! \brief libopenmpt pre-release tag */ /*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL "" #define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */ /*! \brief libopenmpt pre-release flag */

View File

@ -1,8 +1,8 @@
LIBOPENMPT_VERSION_MAJOR=0 LIBOPENMPT_VERSION_MAJOR=0
LIBOPENMPT_VERSION_MINOR=4 LIBOPENMPT_VERSION_MINOR=4
LIBOPENMPT_VERSION_PATCH=5 LIBOPENMPT_VERSION_PATCH=9
LIBOPENMPT_VERSION_PREREL= LIBOPENMPT_VERSION_PREREL=
LIBOPENMPT_LTVER_CURRENT=1 LIBOPENMPT_LTVER_CURRENT=1
LIBOPENMPT_LTVER_REVISION=5 LIBOPENMPT_LTVER_REVISION=9
LIBOPENMPT_LTVER_AGE=1 LIBOPENMPT_LTVER_AGE=1

View File

@ -61,7 +61,8 @@ void X86_Dither(int32 *pBuffer, uint32 nSamples, uint32 nBits, DitherModPlugStat
mov ecx, nBits // ecx = number of bits of noise mov ecx, nBits // ecx = number of bits of noise
mov edi, gDitherA // Noise generation mov edi, gDitherA // Noise generation
mov ebx, gDitherB mov ebx, gDitherB
add ecx, MIXING_ATTENUATION+1 add ecx, MIXING_ATTENUATION
add ecx, 1
push ebp push ebp
mov ebp, eax mov ebp, eax
noiseloop: noiseloop:
@ -117,7 +118,7 @@ static void C_Dither(int32 *pBuffer, std::size_t count, uint32 nBits, DitherModP
while(count--) while(count--)
{ {
*pBuffer += dither_rand(a, b) >> (nBits + MIXING_ATTENUATION + 1); *pBuffer += mpt::rshift_signed(dither_rand(a, b), (nBits + MIXING_ATTENUATION + 1));
pBuffer++; pBuffer++;
} }

View File

@ -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 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<m_Instruments.size(); iIns++) for (uint32 iIns=0; iIns<m_Instruments.size(); iIns++)
{ {
const DLSINSTRUMENT &dlsIns = m_Instruments[iIns]; const DLSINSTRUMENT &dlsIns = m_Instruments[iIns];
@ -956,7 +956,7 @@ bool CDLSBank::UpdateSF2PresetData(SF2LOADERINFO &sf2info, const IFFCHUNK &heade
dlsSmp.dwSampleRate = p.dwSampleRate; dlsSmp.dwSampleRate = p.dwSampleRate;
dlsSmp.byOriginalPitch = p.byOriginalPitch; dlsSmp.byOriginalPitch = p.byOriginalPitch;
dlsSmp.chPitchCorrection = static_cast<int8>(Util::muldivr(p.chPitchCorrection, 128, 100)); dlsSmp.chPitchCorrection = static_cast<int8>(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; dlsSmp.dwLen = (p.dwEnd - p.dwStart) * 2;
if ((p.dwEndloop > p.dwStartloop + 7) && (p.dwStartloop >= p.dwStart)) if ((p.dwEndloop > p.dwStartloop + 7) && (p.dwStartloop >= p.dwStart))
@ -1192,7 +1192,6 @@ bool CDLSBank::Open(FileReader file)
m_szFileName = file.GetFileName(); m_szFileName = file.GetFileName();
file.Rewind(); file.Rewind();
const uint8 *lpMemFile = file.GetRawData<uint8>();
size_t dwMemLength = file.GetLength(); size_t dwMemLength = file.GetLength();
size_t dwMemPos = 0; size_t dwMemPos = 0;
if(!file.CanRead(256)) if(!file.CanRead(256))
@ -1397,13 +1396,14 @@ bool CDLSBank::Open(FileReader file)
Log("ptbl not present: building table (%d wavelinks)...\n", m_nMaxWaveLink); Log("ptbl not present: building table (%d wavelinks)...\n", m_nMaxWaveLink);
#endif #endif
m_WaveForms.reserve(m_nMaxWaveLink); m_WaveForms.reserve(m_nMaxWaveLink);
dwMemPos = m_dwWavePoolOffset; file.Seek(m_dwWavePoolOffset);
while (dwMemPos + sizeof(IFFCHUNK) < dwMemLength) while(m_WaveForms.size() < m_nMaxWaveLink && file.CanRead(sizeof(IFFCHUNK)))
{ {
IFFCHUNK *pchunk = (IFFCHUNK *)(lpMemFile + dwMemPos); IFFCHUNK chunk;
if (pchunk->id == IFFID_LIST) m_WaveForms.push_back(dwMemPos - m_dwWavePoolOffset); file.ReadStruct(chunk);
dwMemPos += 8 + pchunk->len; if (chunk.id == IFFID_LIST)
if (m_WaveForms.size() >= m_nMaxWaveLink) break; m_WaveForms.push_back(file.GetPosition() - m_dwWavePoolOffset - sizeof(IFFCHUNK));
file.Skip(chunk.len);
} }
#ifdef DLSBANK_LOG #ifdef DLSBANK_LOG
Log("Found %d waveforms\n", m_WaveForms.size()); Log("Found %d waveforms\n", m_WaveForms.size());
@ -1467,13 +1467,13 @@ bool CDLSBank::ExtractWaveForm(uint32 nIns, uint32 nRgn, std::vector<uint8> &wav
return false; return false;
} }
long dwOffset = mpt::saturate_cast<long>(m_WaveForms[nWaveLink] + m_dwWavePoolOffset);
mpt::ifstream f(m_szFileName, std::ios::binary); mpt::ifstream f(m_szFileName, std::ios::binary);
if(!f) if(!f)
{ {
return false; return false;
} }
if (mpt::IO::SeekAbsolute(f, dwOffset)) mpt::IO::Offset sampleOffset = mpt::saturate_cast<mpt::IO::Offset>(m_WaveForms[nWaveLink] + m_dwWavePoolOffset);
if(mpt::IO::SeekAbsolute(f, sampleOffset))
{ {
if (m_nType & SOUNDBANK_TYPE_SF2) if (m_nType & SOUNDBANK_TYPE_SF2)
{ {

View File

@ -594,23 +594,25 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags)
uint32 minPtr = Util::MaxValueOfType(minPtr); uint32 minPtr = Util::MaxValueOfType(minPtr);
for(uint32 pos : insPos) for(uint32 pos : insPos)
{ {
if(pos > 0) minPtr = std::min(minPtr, pos); if(pos > 0 && pos < minPtr) minPtr = pos;
} }
for(uint32 pos : smpPos) for(uint32 pos : smpPos)
{ {
if(pos > 0) minPtr = std::min(minPtr, pos); if(pos > 0 && pos < minPtr) minPtr = pos;
} }
for(uint32 pos : patPos) for(uint32 pos : patPos)
{ {
if(pos > 0) minPtr = std::min(minPtr, pos); if(pos > 0 && pos < minPtr) minPtr = pos;
} }
if(fileHeader.special & ITFileHeader::embedSongMessage) if(fileHeader.special & ITFileHeader::embedSongMessage)
{ {
minPtr = std::min<uint32>(minPtr, fileHeader.msgoffset); minPtr = std::min<uint32>(minPtr, fileHeader.msgoffset);
} }
const bool possiblyUNMO3 = fileHeader.cmwt == 0x0214 && fileHeader.cwtv == 0x0214 && fileHeader.highlight_major == 0 && fileHeader.highlight_minor == 0 const bool possiblyUNMO3 = fileHeader.cmwt == 0x0214 && (fileHeader.cwtv == 0x0214 || fileHeader.cwtv == 0)
&& fileHeader.pwd == 0 && fileHeader.reserved == 0 && (fileHeader.flags & (ITFileHeader::useMIDIPitchController | ITFileHeader::reqEmbeddedMIDIConfig)) == 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) 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 // Reading IT Edit History Info
// This is only supposed to be present if bit 1 of the special flags is set. // 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 // 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 // External sample in MPTM file
size_t strLen; size_t strLen;
file.ReadVarInt(strLen); file.ReadVarInt(strLen);
if(loadFlags & loadSampleData) if((loadFlags & loadSampleData) && strLen)
{ {
std::string filenameU8; std::string filenameU8;
file.ReadString<mpt::String::maybeNullTerminated>(filenameU8, strLen); file.ReadString<mpt::String::maybeNullTerminated>(filenameU8, strLen);
#if defined(MPT_EXTERNAL_SAMPLES) #if defined(MPT_EXTERNAL_SAMPLES)
SetSamplePath(i + 1, mpt::PathString::FromUTF8(filenameU8)); SetSamplePath(i + 1, mpt::PathString::FromUTF8(filenameU8));
#elif !defined(LIBOPENMPT_BUILD_TEST) #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 #endif // MPT_EXTERNAL_SAMPLES
} else } else
{ {
@ -1170,7 +1177,7 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags)
&& m_nSamples > 0 && !strcmp(Samples[1].filename, "XXXXXXXX.YYY")) && m_nSamples > 0 && !strcmp(Samples[1].filename, "XXXXXXXX.YYY"))
{ {
madeWithTracker = U_("CheeseTracker"); madeWithTracker = U_("CheeseTracker");
} else if(fileHeader.cwtv == 0) } else if(fileHeader.cwtv == 0 && madeWithTracker.empty())
{ {
madeWithTracker = U_("Unknown"); madeWithTracker = U_("Unknown");
} else if(fileHeader.cmwt < 0x0300 && madeWithTracker.empty()) } 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; uint32 len = 0;
// Maximum 7 bytes per cell, plus end of row marker, so this buffer is always large enough to cover one row. // 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]; 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++) for(CHANNELINDEX ch = 0; ch < maxChannels; ch++, m++)
{ {

View File

@ -516,6 +516,7 @@ static void MIDINoteOff(MidiChannelState &midiChn, std::vector<ModChannelState>
uint8 midiCh = modChnStatus[chn].midiCh; uint8 midiCh = modChnStatus[chn].midiCh;
modChnStatus[chn].note = NOTE_NONE; modChnStatus[chn].note = NOTE_NONE;
modChnStatus[chn].sustained = false;
midiChn.noteOn[note] = CHANNELINDEX_INVALID; midiChn.noteOn[note] = CHANNELINDEX_INVALID;
ModCommand &m = patRow[chn]; ModCommand &m = patRow[chn];
if(m.note == NOTE_NONE) 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 // Release notes that are still being held after note-off
for(const auto &chnState : modChnStatus) 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); MIDINoteOff(midiChnStatus[midiCh], modChnStatus, chnState.note - NOTE_MIN, delay, patRow, drumChns);
} }

View File

@ -210,10 +210,16 @@ struct MO3Instrument
} }
if(mptIns.nMidiChannel != MidiNoChannel) if(mptIns.nMidiChannel != MidiNoChannel)
{ {
if(mptIns.wMidiBank < 128) if(type == MOD_TYPE_XM)
mptIns.wMidiBank = midiBank + 1; {
if(mptIns.nMidiProgram < 128)
mptIns.nMidiProgram = midiPatch + 1; mptIns.nMidiProgram = midiPatch + 1;
} else
{
if(midiBank < 128)
mptIns.wMidiBank = midiBank + 1;
if(midiPatch < 128)
mptIns.nMidiProgram = midiPatch + 1;
}
mptIns.midiPWD = midiBend; mptIns.midiPWD = midiBend;
} }
@ -1579,10 +1585,9 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
sampleChunk.chunk.Rewind(); sampleChunk.chunk.Rewind();
FileReader::PinnedRawDataView sampleChunkView = sampleChunk.chunk.GetPinnedRawDataView(); FileReader::PinnedRawDataView sampleChunkView = sampleChunk.chunk.GetPinnedRawDataView();
mergedData.insert(mergedData.end(), mpt::byte_cast<const char*>(sampleChunkView.begin()), mpt::byte_cast<const char*>(sampleChunkView.end())); mergedData.insert(mergedData.end(), mpt::byte_cast<const char *>(sampleChunkView.begin()), mpt::byte_cast<const char *>(sampleChunkView.end()));
#endif #endif
} }
FileReader mergedDataChunk(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(mergedData))); FileReader mergedDataChunk(mpt::byte_cast<mpt::const_byte_span>(mpt::as_span(mergedData)));
@ -1647,10 +1652,10 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
{ {
if(sample.uFlags[CHN_16BIT]) if(sample.uFlags[CHN_16BIT])
{ {
CopyChannelToInterleaved<SC::Convert<int16, float> >(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); CopyChannelToInterleaved<SC::Convert<int16, float>>(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn);
} else } else
{ {
CopyChannelToInterleaved<SC::Convert<int8, float> >(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); CopyChannelToInterleaved<SC::Convert<int8, float>>(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn);
} }
} }
} }
@ -1687,7 +1692,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
if(sharedHeader) if(sharedHeader)
{ {
FileReader::PinnedRawDataView headChunkView = headerChunk.GetPinnedRawDataView(initialRead); FileReader::PinnedRawDataView headChunkView = headerChunk.GetPinnedRawDataView(initialRead);
vorb = stb_vorbis_open_pushdata(mpt::byte_cast<const unsigned char*>(headChunkView.data()), mpt::saturate_cast<int>(headChunkView.size()), &consumed, &error, nullptr); vorb = stb_vorbis_open_pushdata(mpt::byte_cast<const unsigned char *>(headChunkView.data()), mpt::saturate_cast<int>(headChunkView.size()), &consumed, &error, nullptr);
headerChunk.Skip(consumed); headerChunk.Skip(consumed);
} }
FileReader::PinnedRawDataView sampleDataView = sampleData.GetPinnedRawDataView(); FileReader::PinnedRawDataView sampleDataView = sampleData.GetPinnedRawDataView();
@ -1695,7 +1700,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
std::size_t dataLeft = sampleDataView.size(); std::size_t dataLeft = sampleDataView.size();
if(!sharedHeader) if(!sharedHeader)
{ {
vorb = stb_vorbis_open_pushdata(mpt::byte_cast<const unsigned char*>(data), mpt::saturate_cast<int>(dataLeft), &consumed, &error, nullptr); vorb = stb_vorbis_open_pushdata(mpt::byte_cast<const unsigned char *>(data), mpt::saturate_cast<int>(dataLeft), &consumed, &error, nullptr);
sampleData.Skip(consumed); sampleData.Skip(consumed);
data += consumed; data += consumed;
dataLeft -= consumed; dataLeft -= consumed;
@ -1711,7 +1716,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
{ {
int channels = 0, decodedSamples = 0; int channels = 0, decodedSamples = 0;
float **output; float **output;
consumed = stb_vorbis_decode_frame_pushdata(vorb, mpt::byte_cast<const unsigned char*>(data), mpt::saturate_cast<int>(dataLeft), &channels, &output, &decodedSamples); consumed = stb_vorbis_decode_frame_pushdata(vorb, mpt::byte_cast<const unsigned char *>(data), mpt::saturate_cast<int>(dataLeft), &channels, &output, &decodedSamples);
sampleData.Skip(consumed); sampleData.Skip(consumed);
data += consumed; data += consumed;
dataLeft -= consumed; dataLeft -= consumed;
@ -1721,9 +1726,9 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
for(int chn = 0; chn < channels; chn++) for(int chn = 0; chn < channels; chn++)
{ {
if(sample.uFlags[CHN_16BIT]) if(sample.uFlags[CHN_16BIT])
CopyChannelToInterleaved<SC::Convert<int16, float> >(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); CopyChannelToInterleaved<SC::Convert<int16, float>>(sample.sample16() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn);
else else
CopyChannelToInterleaved<SC::Convert<int8, float> >(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn); CopyChannelToInterleaved<SC::Convert<int8, float>>(sample.sample8() + offset * sample.GetNumChannels(), output[chn], channels, decodedSamples, chn);
} }
} }
offset += decodedSamples; offset += decodedSamples;

View File

@ -456,14 +456,14 @@ struct PT36IffChunk
// IFF chunk names // IFF chunk names
enum ChunkIdentifiers enum ChunkIdentifiers
{ {
idVERS = MagicBE("VERS"), idVERS = MagicBE("VERS"),
idINFO = MagicBE("INFO"), idINFO = MagicBE("INFO"),
idCMNT = MagicBE("CMNT"), idCMNT = MagicBE("CMNT"),
idPTDT = MagicBE("PTDT"), idPTDT = MagicBE("PTDT"),
}; };
uint32be signature; // IFF chunk name uint32be signature; // IFF chunk name
uint32be chunksize; // chunk size without header uint32be chunksize; // chunk size without header
}; };
MPT_BINARY_STRUCT(PT36IffChunk, 8) 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. // 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) 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 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 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 numPatternsIllegal = 0; // Total number of patterns in file, also counting in "invalid" pattern indexes >= 128
for(ORDERINDEX ord = 0; ord < 128; ord++) for(ORDERINDEX ord = 0; ord < 128; ord++)
{ {
@ -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). // 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... // 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_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 // Setup channel pan positions and volume
SetupMODPanning(); SetupMODPanning();
@ -930,10 +930,10 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
// - Detect 7-bit panning. // - Detect 7-bit panning.
bool onlyAmigaNotes = true; bool onlyAmigaNotes = true;
bool fix7BitPanning = false; bool fix7BitPanning = false;
uint8 maxPanning = 0; // For detecting 8xx-as-sync uint8 maxPanning = 0; // For detecting 8xx-as-sync
if(!isNoiseTracker) if(!isNoiseTracker)
{ {
bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning
isNoiseTracker = isMdKd; isNoiseTracker = isMdKd;
for(PATTERNINDEX pat = 0; pat < numPatterns; pat++) for(PATTERNINDEX pat = 0; pat < numPatterns; pat++)
{ {
@ -963,7 +963,7 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
extendedPanning = true; extendedPanning = true;
} else if(m.command == 0x0E && (m.param & 0xF0) == 0x80) } else if(m.command == 0x0E && (m.param & 0xF0) == 0x80)
{ {
maxPanning = std::max<uint8>(maxPanning, m.param << 4); maxPanning = std::max<uint8>(maxPanning, (m.param & 0x0F) << 4);
} }
} }
} }
@ -1342,7 +1342,6 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)
totalSampleLen += sampleHeader.length; totalSampleLen += sampleHeader.length;
allVolumes |= sampleHeader.volume; 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) // 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)
@ -2290,6 +2289,7 @@ bool CSoundFile::SaveMod(std::ostream &f) const
mpt::IO::Write(f, modMagic); mpt::IO::Write(f, modMagic);
// Write patterns // Write patterns
bool invalidInstruments = false;
std::vector<uint8> events; std::vector<uint8> events;
for(PATTERNINDEX pat = 0; pat < writePatterns; pat++) for(PATTERNINDEX pat = 0; pat < writePatterns; pat++)
{ {
@ -2314,7 +2314,7 @@ bool CSoundFile::SaveMod(std::ostream &f) const
events.resize(writeChannels * 4); events.resize(writeChannels * 4);
size_t eventByte = 0; size_t eventByte = 0;
for(CHANNELINDEX chn = 0; chn < writeChannels; chn++) for(CHANNELINDEX chn = 0; chn < writeChannels; chn++, eventByte += 4)
{ {
ModCommand &m = rowBase[chn]; ModCommand &m = rowBase[chn];
uint8 command = m.command, param = m.param; 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]; 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 + 0] = ((period >> 8) & 0x0F) | (instr & 0x10);
events[eventByte++] = period & 0xFF; events[eventByte + 1] = period & 0xFF;
events[eventByte++] = ((instr & 0x0F) << 4) | (command & 0x0F); events[eventByte + 2] = ((instr & 0x0F) << 4) | (command & 0x0F);
events[eventByte++] = param; 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 //Check for unsaved patterns
for(PATTERNINDEX pat = writePatterns; pat < Patterns.Size(); pat++) for(PATTERNINDEX pat = writePatterns; pat < Patterns.Size(); pat++)
{ {

View File

@ -1156,7 +1156,7 @@ bool CSoundFile::ReadMT2(FileReader &file, ModLoadingFlags loadFlags)
} }
SetSamplePath(i + 1, mpt::PathString::FromLocaleSilent(filename)); SetSamplePath(i + 1, mpt::PathString::FromLocaleSilent(filename));
#elif !defined(LIBOPENMPT_BUILD_TEST) #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 #endif // MPT_EXTERNAL_SAMPLES
} }
} }

View File

@ -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. // 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; return nArpeggioLastNote;
} }
ModCommand::NOTE plugNote = nNote; ModCommand::NOTE plugNote = mpt::saturate_cast<ModCommand::NOTE>(nNote - nTranspose);
// Caution: When in compatible mode, ModChannel::nNote stores the "real" note, not the mapped note! // 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]; plugNote = pModInstrument->NoteMap[plugNote - NOTE_MIN];
} }

View File

@ -25,6 +25,7 @@
#include "modsmp_ctrl.h" // For updating the loop wraparound data with the invert loop effect #include "modsmp_ctrl.h" // For updating the loop wraparound data with the invert loop effect
#include "plugins/PlugInterface.h" #include "plugins/PlugInterface.h"
#include "OPL.h" #include "OPL.h"
#include "MIDIEvents.h"
OPENMPT_NAMESPACE_BEGIN OPENMPT_NAMESPACE_BEGIN
@ -83,7 +84,9 @@ public:
void Reset() void Reset()
{ {
#ifndef NO_PLUGINS
plugParams.clear(); plugParams.clear();
#endif
elapsedTime = 0.0; elapsedTime = 0.0;
state->m_lTotalSampleCount = 0; state->m_lTotalSampleCount = 0;
state->m_nMusicSpeed = sndFile.m_nDefaultSpeed; 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) if((chn.nCutOff < 0x7F || m_playBehaviour[kITFilterBehaviour]) && useFilter)
{ {
int cutoff = SetupChannelFilter(chn, true); 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); m_opl->Volume(channelHint, chn.nCutOff / 2u, true);
} }
} }
@ -2635,7 +2638,7 @@ bool CSoundFile::ProcessEffects()
{ {
note = NOTE_NONE; note = NOTE_NONE;
} }
} else if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetNumInstruments() != 0 && ModCommand::IsNoteOrEmpty(static_cast<ModCommand::NOTE>(note))) } else if((GetType() & (MOD_TYPE_IT | MOD_TYPE_MPT | MOD_TYPE_J2B)) && GetNumInstruments() != 0 && ModCommand::IsNoteOrEmpty(static_cast<ModCommand::NOTE>(note)))
{ {
// IT compatibility: Invalid instrument numbers do nothing, but they are remembered for upcoming notes and do not trigger a note in that case. // 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 // Test case: InstrumentNumberChange.it
@ -5454,7 +5457,7 @@ void CSoundFile::RetrigNote(CHANNELINDEX nChn, int param, int offset)
bool fading = chn.dwFlags[CHN_NOTEFADE]; bool fading = chn.dwFlags[CHN_NOTEFADE];
// IT compatibility: Really weird combination of envelopes and retrigger (see Storlek's q.it testcase) // IT compatibility: Really weird combination of envelopes and retrigger (see Storlek's q.it testcase)
// Test case: retrig.it // 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. // XM compatibility: Prevent NoteChange from resetting the fade flag in case an instrument number + note-off is present.
// Test case: RetrigFade.xm // Test case: RetrigFade.xm
if(fading && GetType() == MOD_TYPE_XM) if(fading && GetType() == MOD_TYPE_XM)

View File

@ -64,9 +64,9 @@ OPENMPT_NAMESPACE_BEGIN
// MODULAR ModInstrument FIELD ACCESS : body content in InstrumentExtensions.cpp // MODULAR ModInstrument FIELD ACCESS : body content in InstrumentExtensions.cpp
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#ifndef MODPLUG_NO_FILESAVE #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 #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);
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------

View File

@ -1817,13 +1817,13 @@ void CSoundFile::ProcessSampleAutoVibrato(ModChannel &chn, int &period, Tuning::
default: default:
if(GetType() != MOD_TYPE_MT2) if(GetType() != MOD_TYPE_MT2)
{ {
vdelta = ft2VibratoTable[chn.nAutoVibPos & 0xFF]; vdelta = -ITSinusTable[chn.nAutoVibPos & 0xFF];
} else } else
{ {
// Fix flat-sounding pads in "another worlds" by Eternal Engine. // Fix flat-sounding pads in "another worlds" by Eternal Engine.
// Vibrato starts at the maximum amplitude of the sine wave // Vibrato starts at the maximum amplitude of the sine wave
// and the vibrato frequency never decreases below the original note's frequency. // 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; int n = (vdelta * chn.nAutoVibDepth) / 256;

View File

@ -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)) // round(65536 * 2**(n/768))
// 768 = 64 extra-fine finetune steps for 12 notes // 768 = 64 extra-fine finetune steps for 12 notes
// Table content is in 16.16 format // Table content is in 16.16 format
@ -782,7 +760,6 @@ void CResampler::InitFloatmixerTables()
void CResampler::InitializeTablesFromScratch(bool force) void CResampler::InitializeTablesFromScratch(bool force)
{ {
bool initParameterIndependentTables = false; bool initParameterIndependentTables = false;
if(force) if(force)
{ {

View File

@ -31,7 +31,6 @@ extern const int8 retrigTable1[16];
extern const int8 retrigTable2[16]; extern const int8 retrigTable2[16];
extern const uint16 XMPeriodTable[104]; extern const uint16 XMPeriodTable[104];
extern const uint32 XMLinearTable[768]; extern const uint32 XMLinearTable[768];
extern const int8 ft2VibratoTable[256];
extern const uint32 FineLinearSlideUpTable[16]; extern const uint32 FineLinearSlideUpTable[16];
extern const uint32 FineLinearSlideDownTable[16]; extern const uint32 FineLinearSlideDownTable[16];
extern const uint32 LinearSlideUpTable[256]; extern const uint32 LinearSlideUpTable[256];

View File

@ -179,7 +179,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd
param = 0x91; param = 0x91;
} else } else
{ {
param = std::min<PARAM>(param << 1, 0xFF); param = mpt::saturate_cast<PARAM>(param * 2u);
} }
} }
} // End if(command == CMD_PANNING8) } // 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>((param & 0x0F) * 2u, 15); param = (param & 0xF0) | std::min<PARAM>((param & 0x0F) * 2u, 15);
break; break;
case CMD_GLOBALVOLUME: case CMD_GLOBALVOLUME:
param = std::min<PARAM>(0x80, param * 2u); param = std::min<PARAM>(0x40, param) * 2u;
break; break;
} }
} // End if(oldTypeIsIT_MPT && newTypeIsXM) } // End if(oldTypeIsIT_MPT && newTypeIsXM)
@ -776,7 +776,7 @@ void ModCommand::Convert(MODTYPE fromType, MODTYPE toType, const CSoundFile &snd
if(newTypeIsIT_MPT) if(newTypeIsIT_MPT)
{ {
// Convert some commands which behave differently or don't exist // 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: case VOLCMD_PANSLIDELEFT:
command = CMD_PANNINGSLIDE; command = CMD_PANNINGSLIDE;

View File

@ -12,6 +12,9 @@
#include "BuildSettings.h" #include "BuildSettings.h"
#include "../../common/mptAlloc.h"
OPENMPT_NAMESPACE_BEGIN OPENMPT_NAMESPACE_BEGIN
@ -25,7 +28,11 @@ protected:
std::vector<buffer_t *> inputs; // Pointers to input buffers std::vector<buffer_t *> inputs; // Pointers to input buffers
std::vector<buffer_t *> outputs; // Pointers to output buffers std::vector<buffer_t *> outputs; // Pointers to output buffers
#if defined(MPT_ENABLE_ALIGNED_ALLOC)
mpt::aligned_buffer<buffer_t, 16> alignedBuffer; // Aligned buffer pointed into mpt::aligned_buffer<buffer_t, 16> alignedBuffer; // Aligned buffer pointed into
#else
std::vector<buffer_t> alignedBuffer;
#endif
// Return pointer to an aligned buffer // Return pointer to an aligned buffer
const buffer_t *GetBuffer(size_t index) const const buffer_t *GetBuffer(size_t index) const
@ -56,7 +63,11 @@ public:
outputs.resize(numOutputs); outputs.resize(numOutputs);
// Create inputs + outputs buffers // 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) } MPT_EXCEPTION_CATCH_OUT_OF_MEMORY(e)
{ {
@ -65,7 +76,11 @@ public:
inputs.shrink_to_fit(); inputs.shrink_to_fit();
outputs.clear(); outputs.clear();
outputs.shrink_to_fit(); 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; return false;
} }

View File

@ -32,6 +32,7 @@
#include "../soundlib/ITCompression.h" #include "../soundlib/ITCompression.h"
#include "../soundlib/tuningcollection.h" #include "../soundlib/tuningcollection.h"
#include "../soundlib/tuning.h" #include "../soundlib/tuning.h"
#include "../soundlib/Dither.h"
#ifdef MODPLUG_TRACKER #ifdef MODPLUG_TRACKER
#include "../mptrack/Mptrack.h" #include "../mptrack/Mptrack.h"
#include "../mptrack/Moddoc.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")); VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull).ToUString(), U_("2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"));
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO) #if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), "2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32"_uuid); constexpr mpt::UUID uuid_tmp = "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), uuid_tmp);
VERIFY_EQUAL(mpt::UUID(0x2ed6593au, 0xdfe6, 0x4cf8, 0xb2e575ad7f600c32ull), mpt::UUID(Util::StringToCLSID(L"{2ed6593a-dfe6-4cf8-b2e5-75ad7f600c32}"))); 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 #endif
#if defined(MODPLUG_TRACKER) || !defined(NO_DMO) #if defined(MODPLUG_TRACKER) || !defined(NO_DMO)
@ -4714,6 +4716,82 @@ static MPT_NOINLINE void TestSampleConversion()
VERIFY_EQUAL_NONCONT(signed8[3], 0); VERIFY_EQUAL_NONCONT(signed8[3], 0);
} }
// Dither
{
std::vector<mixsample_t> buffer(64);
Dither dither(mpt::global_random_device());
dither.SetMode(DitherModPlug);
dither.Process(buffer.data(), 64, 1, 16);
std::vector<mixsample_t> 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]);
}
}
} }