Updated libOpenMPT to version 0.7.13
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
4b19c15354
commit
9ed4e4e8d9
50 changed files with 524 additions and 185 deletions
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors
|
Copyright (c) 2004-2025, OpenMPT Project Developers and Contributors
|
||||||
Copyright (c) 1997-2003, Olivier Lapicque
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,27 @@ NUMTHREADS:=$(shell nproc)
|
||||||
|
|
||||||
else ifeq ($(OS),Windows_NT)
|
else ifeq ($(OS),Windows_NT)
|
||||||
|
|
||||||
|
ifeq ($(shell uname -o),Cygwin)
|
||||||
|
|
||||||
|
HOST=unix
|
||||||
|
HOST_FLAVOUR=CYGWIN
|
||||||
|
|
||||||
|
TOOLCHAIN_SUFFIX=
|
||||||
|
|
||||||
|
CPPCHECK = cppcheck
|
||||||
|
|
||||||
|
MKDIR_P = mkdir -p
|
||||||
|
RM = rm -f
|
||||||
|
RMTREE = rm -rf
|
||||||
|
INSTALL = install
|
||||||
|
INSTALL_MAKE_DIR = install -d
|
||||||
|
INSTALL_DIR = cp -r -v
|
||||||
|
FIXPATH = $1
|
||||||
|
|
||||||
|
NUMTHREADS:=$(NUMBER_OF_PROCESSORS)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
HOST=windows
|
HOST=windows
|
||||||
HOST_FLAVOUR=
|
HOST_FLAVOUR=
|
||||||
|
|
||||||
|
@ -273,6 +294,8 @@ FIXPATH = $(subst /,\,$1)
|
||||||
|
|
||||||
NUMTHREADS:=$(NUMBER_OF_PROCESSORS)
|
NUMTHREADS:=$(NUMBER_OF_PROCESSORS)
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
HOST=unix
|
HOST=unix
|
||||||
|
@ -689,7 +712,7 @@ ifeq ($(LOCAL_MPG123),1)
|
||||||
CPPFLAGS_MPG123 := -DMPT_WITH_MPG123 -DMPG123_NO_LARGENAME
|
CPPFLAGS_MPG123 := -DMPT_WITH_MPG123 -DMPG123_NO_LARGENAME
|
||||||
LDFLAGS_MPG123 :=
|
LDFLAGS_MPG123 :=
|
||||||
LDLIBS_MPG123 :=
|
LDLIBS_MPG123 :=
|
||||||
CPPFLAGS_MPG123 += -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/makefile/
|
CPPFLAGS_MPG123 += -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/generic/
|
||||||
LOCAL_MPG123_SOURCES :=
|
LOCAL_MPG123_SOURCES :=
|
||||||
LOCAL_MPG123_SOURCES += include/mpg123/src/compat/compat.c
|
LOCAL_MPG123_SOURCES += include/mpg123/src/compat/compat.c
|
||||||
LOCAL_MPG123_SOURCES += include/mpg123/src/compat/compat_str.c
|
LOCAL_MPG123_SOURCES += include/mpg123/src/compat/compat_str.c
|
||||||
|
@ -721,10 +744,10 @@ include/mpg123/src/compat/%$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENER
|
||||||
include/mpg123/src/compat/%.test$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
include/mpg123/src/compat/%.test$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
include/mpg123/src/libmpg123/%$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
include/mpg123/src/libmpg123/%$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
include/mpg123/src/libmpg123/%.test$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
include/mpg123/src/libmpg123/%.test$(FLAVOUR_O).o : CFLAGS+=$(CFLAGS_SILENT) -DOPT_GENERIC
|
||||||
include/mpg123/src/compat/%$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/makefile/ $(CPPFLAGS)
|
include/mpg123/src/compat/%$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/generic/ $(CPPFLAGS)
|
||||||
include/mpg123/src/compat/%.test$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/makefile/ $(CPPFLAGS)
|
include/mpg123/src/compat/%.test$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/generic/ $(CPPFLAGS)
|
||||||
include/mpg123/src/libmpg123/%$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/makefile/ $(CPPFLAGS)
|
include/mpg123/src/libmpg123/%$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/generic/ $(CPPFLAGS)
|
||||||
include/mpg123/src/libmpg123/%.test$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/makefile/ $(CPPFLAGS)
|
include/mpg123/src/libmpg123/%.test$(FLAVOUR_O).o : CPPFLAGS:= -Iinclude/mpg123/src/include/ -Iinclude/mpg123/ports/generic/ $(CPPFLAGS)
|
||||||
else
|
else
|
||||||
ifeq ($(NO_MPG123),1)
|
ifeq ($(NO_MPG123),1)
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
MPT_SVNVERSION=22406
|
MPT_SVNVERSION=22826
|
||||||
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.7.12
|
MPT_SVNURL=https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.7.13
|
||||||
MPT_SVNDATE=2024-12-01T13:10:15.135688Z
|
MPT_SVNDATE=2025-01-06T13:49:43.586768Z
|
||||||
|
|
|
@ -99,7 +99,7 @@ download "build/externals/allegro-4.2.3.1-hg.8+r8500.zip" 3872466 46cd8d4d7138b7
|
||||||
download "build/externals/csdpmi7b.zip" 71339 58c24691d27cead1cec92d334af551f37a3ba31de25a687d99399c28d822ec9f6ffccc9332bfce35e65dae4dd1210b54e54b223a4de17f5adcb11e2da004b834 "https://lib.openmpt.org/files/libopenmpt/contrib/djgpp/cwsdpmi/csdpmi7b.zip https://djgpp.mirror.garr.it/current/v2misc/csdpmi7b.zip"
|
download "build/externals/csdpmi7b.zip" 71339 58c24691d27cead1cec92d334af551f37a3ba31de25a687d99399c28d822ec9f6ffccc9332bfce35e65dae4dd1210b54e54b223a4de17f5adcb11e2da004b834 "https://lib.openmpt.org/files/libopenmpt/contrib/djgpp/cwsdpmi/csdpmi7b.zip https://djgpp.mirror.garr.it/current/v2misc/csdpmi7b.zip"
|
||||||
download "build/externals/csdpmi7s.zip" 89872 ea5652d31850d8eb0d15a919de0b51849f58efea0d16ad2aa4687fac4abd223d0ca34a2d1b616b02fafe84651dbef3e506df9262cfb399eb6d9909bffc89bfd3 "https://lib.openmpt.org/files/libopenmpt/contrib/djgpp/cwsdpmi/csdpmi7s.zip https://djgpp.mirror.garr.it/current/v2misc/csdpmi7s.zip"
|
download "build/externals/csdpmi7s.zip" 89872 ea5652d31850d8eb0d15a919de0b51849f58efea0d16ad2aa4687fac4abd223d0ca34a2d1b616b02fafe84651dbef3e506df9262cfb399eb6d9909bffc89bfd3 "https://lib.openmpt.org/files/libopenmpt/contrib/djgpp/cwsdpmi/csdpmi7s.zip https://djgpp.mirror.garr.it/current/v2misc/csdpmi7s.zip"
|
||||||
download "build/externals/WA5.55_SDK.exe" 336166 394375db8a16bf155b5de9376f6290488ab339e503dbdfdc4e2f5bede967799e625c559cca363bc988324f1a8e86e5fd28a9f697422abd7bb3dcde4a766607b5 "http://download.nullsoft.com/winamp/plugin-dev/WA5.55_SDK.exe https://web.archive.org/web/20131217072017id_/http://download.nullsoft.com/winamp/plugin-dev/WA5.55_SDK.exe"
|
download "build/externals/WA5.55_SDK.exe" 336166 394375db8a16bf155b5de9376f6290488ab339e503dbdfdc4e2f5bede967799e625c559cca363bc988324f1a8e86e5fd28a9f697422abd7bb3dcde4a766607b5 "http://download.nullsoft.com/winamp/plugin-dev/WA5.55_SDK.exe https://web.archive.org/web/20131217072017id_/http://download.nullsoft.com/winamp/plugin-dev/WA5.55_SDK.exe"
|
||||||
download "build/externals/xmp-sdk.zip" 322744 62c442d656d4bb380360368a0f5f01da11b4ed54333d7f54f875a9a5ec390b08921e00bd08e62cd7a0a5fe642e3377023f20a950cc2a42898ff4cda9ab88fc91 "https://www.un4seen.com/files/xmp-sdk.zip"
|
download "build/externals/xmp-sdk.zip" 322903 67b96c6e6aa794e9de4f446d23f969e3591457196fd100c5475f5df52308de861a0c411db54fcb2bf46a12e9136ddda9d2974a5167432a979a701ef2c4679ef9 "https://www.un4seen.com/files/xmp-sdk.zip"
|
||||||
|
|
||||||
unpack "include/allegro42" "build/externals/allegro-4.2.3.1-hg.8+r8500.zip" "."
|
unpack "include/allegro42" "build/externals/allegro-4.2.3.1-hg.8+r8500.zip" "."
|
||||||
unpack "include/cwsdpmi" "build/externals/csdpmi7b.zip" "."
|
unpack "include/cwsdpmi" "build/externals/csdpmi7b.zip" "."
|
||||||
|
|
84
Frameworks/OpenMPT/OpenMPT/build/make/config-cygwin.mk
Normal file
84
Frameworks/OpenMPT/OpenMPT/build/make/config-cygwin.mk
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
ifeq ($(origin CC),default)
|
||||||
|
CC = $(TOOLCHAIN_PREFIX)gcc$(TOOLCHAIN_SUFFIX)
|
||||||
|
endif
|
||||||
|
ifeq ($(origin CXX),default)
|
||||||
|
CXX = $(TOOLCHAIN_PREFIX)g++$(TOOLCHAIN_SUFFIX)
|
||||||
|
endif
|
||||||
|
ifeq ($(origin LD),default)
|
||||||
|
LD = $(CXX)
|
||||||
|
endif
|
||||||
|
ifeq ($(origin AR),default)
|
||||||
|
AR = $(TOOLCHAIN_PREFIX)ar$(TOOLCHAIN_SUFFIX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(STDCXX),)
|
||||||
|
CXXFLAGS_STDCXX = -std=$(STDCXX) -fexceptions -frtti -pthread
|
||||||
|
else ifeq ($(shell printf '\n' > bin/empty.cpp ; if $(CXX) -std=c++20 -c bin/empty.cpp -o bin/empty.out > /dev/null 2>&1 ; then echo 'c++20' ; fi ), c++20)
|
||||||
|
CXXFLAGS_STDCXX = -std=c++20 -fexceptions -frtti -pthread
|
||||||
|
else
|
||||||
|
CXXFLAGS_STDCXX = -std=c++17 -fexceptions -frtti -pthread
|
||||||
|
endif
|
||||||
|
ifneq ($(STDC),)
|
||||||
|
CFLAGS_STDC = -std=$(STDC) -pthread
|
||||||
|
else ifeq ($(shell printf '\n' > bin/empty.c ; if $(CC) -std=c18 -c bin/empty.c -o bin/empty.out > /dev/null 2>&1 ; then echo 'c18' ; fi ), c18)
|
||||||
|
CFLAGS_STDC = -std=c18 -pthread
|
||||||
|
else ifeq ($(shell printf '\n' > bin/empty.c ; if $(CC) -std=c17 -c bin/empty.c -o bin/empty.out > /dev/null 2>&1 ; then echo 'c17' ; fi ), c17)
|
||||||
|
CFLAGS_STDC = -std=c17 -pthread
|
||||||
|
else
|
||||||
|
CFLAGS_STDC = -std=c11 -pthread
|
||||||
|
endif
|
||||||
|
CXXFLAGS += $(CXXFLAGS_STDCXX)
|
||||||
|
CFLAGS += $(CFLAGS_STDC)
|
||||||
|
LDFLAGS += -pthread
|
||||||
|
|
||||||
|
CPPFLAGS +=
|
||||||
|
CXXFLAGS += -fPIC
|
||||||
|
CFLAGS += -fPIC
|
||||||
|
LDFLAGS +=
|
||||||
|
LDLIBS += -lm
|
||||||
|
ARFLAGS := rcs
|
||||||
|
|
||||||
|
ifeq ($(NATIVE),1)
|
||||||
|
CXXFLAGS += -march=native
|
||||||
|
CFLAGS += -march=native
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(MODERN),1)
|
||||||
|
LDFLAGS += -fuse-ld=gold
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OPTIMIZE_LTO),1)
|
||||||
|
CXXFLAGS += -flto
|
||||||
|
CFLAGS += -flto
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ANALYZE),1)
|
||||||
|
CXXFLAGS += -fanalyzer -Wno-analyzer-malloc-leak -Wno-analyzer-null-dereference -Wno-analyzer-possible-null-argument -Wno-analyzer-possible-null-dereference
|
||||||
|
CFLAGS += -fanalyzer -Wno-analyzer-malloc-leak -Wno-analyzer-null-dereference -Wno-analyzer-possible-null-argument -Wno-analyzer-possible-null-dereference
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CHECKED_ADDRESS),1)
|
||||||
|
CXXFLAGS += -fsanitize=address
|
||||||
|
CFLAGS += -fsanitize=address
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CHECKED_UNDEFINED),1)
|
||||||
|
CXXFLAGS += -fsanitize=undefined
|
||||||
|
CFLAGS += -fsanitize=undefined
|
||||||
|
endif
|
||||||
|
|
||||||
|
include build/make/warnings-gcc.mk
|
||||||
|
|
||||||
|
EXESUFFIX=.exe
|
||||||
|
SOSUFFIX=.dll
|
||||||
|
SOSUFFIXWINDOWS=1
|
||||||
|
|
||||||
|
ALLOW_LGPL=0
|
||||||
|
|
||||||
|
DYNLINK=0
|
||||||
|
SHARED_LIB=1
|
||||||
|
STATIC_LIB=0
|
||||||
|
SHARED_SONAME=0
|
||||||
|
|
||||||
|
ENABLE_DLL=1
|
|
@ -25,6 +25,10 @@ WINDOWS_ARCH=x86
|
||||||
include build/make/config-mingw-w64.mk
|
include build/make/config-mingw-w64.mk
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
else ifeq ($(HOST_FLAVOUR),CYGWIN)
|
||||||
|
|
||||||
|
include build/make/config-cygwin.mk
|
||||||
|
|
||||||
else ifeq ($(HOST_FLAVOUR),LINUX)
|
else ifeq ($(HOST_FLAVOUR),LINUX)
|
||||||
|
|
||||||
include build/make/config-gcc.mk
|
include build/make/config-gcc.mk
|
||||||
|
|
|
@ -55,10 +55,12 @@ CFLAGS += $(CFLAGS_STDC)
|
||||||
|
|
||||||
CPPFLAGS += -DNOMINMAX
|
CPPFLAGS += -DNOMINMAX
|
||||||
ifeq ($(MINGW_COMPILER),clang)
|
ifeq ($(MINGW_COMPILER),clang)
|
||||||
|
CPPFLAGS += -D_UNICODE
|
||||||
CXXFLAGS += -municode
|
CXXFLAGS += -municode
|
||||||
CFLAGS += -municode
|
CFLAGS += -municode
|
||||||
LDFLAGS += -mconsole -mthreads
|
LDFLAGS += -mconsole -mthreads
|
||||||
else
|
else
|
||||||
|
CPPFLAGS += -D_UNICODE
|
||||||
CXXFLAGS += -municode -mthreads
|
CXXFLAGS += -municode -mthreads
|
||||||
CFLAGS += -municode -mthreads
|
CFLAGS += -municode -mthreads
|
||||||
LDFLAGS += -mconsole
|
LDFLAGS += -mconsole
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#define OPENMPT_VERSION_SVNVERSION "22406"
|
#define OPENMPT_VERSION_SVNVERSION "22826"
|
||||||
#define OPENMPT_VERSION_REVISION 22406
|
#define OPENMPT_VERSION_REVISION 22826
|
||||||
#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.7.12"
|
#define OPENMPT_VERSION_URL "https://source.openmpt.org/svn/openmpt/tags/libopenmpt-0.7.13"
|
||||||
#define OPENMPT_VERSION_DATE "2024-12-01T13:10:15.135688Z"
|
#define OPENMPT_VERSION_DATE "2025-01-06T13:49:43.586768Z"
|
||||||
#define OPENMPT_VERSION_IS_PACKAGE 1
|
#define OPENMPT_VERSION_IS_PACKAGE 1
|
||||||
|
|
||||||
|
|
|
@ -257,7 +257,7 @@
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SYMROOT = "../../../bin/debug/xcode4-ios/all";
|
SYMROOT = "../../../bin/debug/xcode4-ios/all";
|
||||||
USER_HEADER_SEARCH_PATHS = (
|
USER_HEADER_SEARCH_PATHS = (
|
||||||
../../../include/mpg123/ports/Xcode,
|
../../../include/mpg123/ports/generic,
|
||||||
../../../include/mpg123/src/include,
|
../../../include/mpg123/src/include,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -295,7 +295,7 @@
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
SYMROOT = "../../../bin/release/xcode4-ios/all";
|
SYMROOT = "../../../bin/release/xcode4-ios/all";
|
||||||
USER_HEADER_SEARCH_PATHS = (
|
USER_HEADER_SEARCH_PATHS = (
|
||||||
../../../include/mpg123/ports/Xcode,
|
../../../include/mpg123/ports/generic,
|
||||||
../../../include/mpg123/src/include,
|
../../../include/mpg123/src/include,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -257,7 +257,7 @@
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SYMROOT = "../../../bin/debug/xcode4-macosx/all";
|
SYMROOT = "../../../bin/debug/xcode4-macosx/all";
|
||||||
USER_HEADER_SEARCH_PATHS = (
|
USER_HEADER_SEARCH_PATHS = (
|
||||||
../../../include/mpg123/ports/Xcode,
|
../../../include/mpg123/ports/generic,
|
||||||
../../../include/mpg123/src/include,
|
../../../include/mpg123/src/include,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -295,7 +295,7 @@
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
SYMROOT = "../../../bin/release/xcode4-macosx/all";
|
SYMROOT = "../../../bin/release/xcode4-macosx/all";
|
||||||
USER_HEADER_SEARCH_PATHS = (
|
USER_HEADER_SEARCH_PATHS = (
|
||||||
../../../include/mpg123/ports/Xcode,
|
../../../include/mpg123/ports/generic,
|
||||||
../../../include/mpg123/src/include,
|
../../../include/mpg123/src/include,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -429,7 +429,11 @@ inline mpt::ustring ToUnicode(uint16 codepage, Tencoding &&fallback, Tsrc &&str)
|
||||||
std::optional<mpt::common_encoding> charset = mpt::optional_encoding_from_codepage(codepage);
|
std::optional<mpt::common_encoding> charset = mpt::optional_encoding_from_codepage(codepage);
|
||||||
if(charset.has_value())
|
if(charset.has_value())
|
||||||
{
|
{
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE)
|
||||||
|
result = mpt::transcode<mpt::ustring>(*charset, std::forward<Tsrc>(str));
|
||||||
|
#else
|
||||||
result = mpt::transcode<mpt::ustring>(charset.value(), std::forward<Tsrc>(str));
|
result = mpt::transcode<mpt::ustring>(charset.value(), std::forward<Tsrc>(str));
|
||||||
|
#endif
|
||||||
} else if(mpt::has_codepage(static_cast<UINT>(codepage)))
|
} else if(mpt::has_codepage(static_cast<UINT>(codepage)))
|
||||||
{
|
{
|
||||||
result = mpt::transcode<mpt::ustring>(static_cast<UINT>(codepage), std::forward<Tsrc>(str));
|
result = mpt::transcode<mpt::ustring>(static_cast<UINT>(codepage), std::forward<Tsrc>(str));
|
||||||
|
@ -440,7 +444,11 @@ inline mpt::ustring ToUnicode(uint16 codepage, Tencoding &&fallback, Tsrc &&str)
|
||||||
return result;
|
return result;
|
||||||
#else // !MPT_OS_WINDOWS
|
#else // !MPT_OS_WINDOWS
|
||||||
std::optional<mpt::common_encoding> charset = mpt::optional_encoding_from_codepage(codepage);
|
std::optional<mpt::common_encoding> charset = mpt::optional_encoding_from_codepage(codepage);
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE)
|
||||||
return charset.has_value() ? mpt::transcode<mpt::ustring>(charset.value(), std::forward<Tsrc>(str)) : mpt::transcode<mpt::ustring>(std::forward<Tencoding>(fallback), std::forward<Tsrc>(str));
|
return charset.has_value() ? mpt::transcode<mpt::ustring>(charset.value(), std::forward<Tsrc>(str)) : mpt::transcode<mpt::ustring>(std::forward<Tencoding>(fallback), std::forward<Tsrc>(str));
|
||||||
|
#else
|
||||||
|
return charset.has_value() ? mpt::transcode<mpt::ustring>(*charset, std::forward<Tsrc>(str)) : mpt::transcode<mpt::ustring>(std::forward<Tencoding>(fallback), std::forward<Tsrc>(str));
|
||||||
|
#endif
|
||||||
#endif // MPT_OS_WINDOWS
|
#endif // MPT_OS_WINDOWS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -600,12 +600,12 @@ mpt::ustring GetFullCreditsString()
|
||||||
"libopenmpt (based on OpenMPT / Open ModPlug Tracker)\n"
|
"libopenmpt (based on OpenMPT / Open ModPlug Tracker)\n"
|
||||||
#endif
|
#endif
|
||||||
"\n"
|
"\n"
|
||||||
"Copyright \xC2\xA9 2004-2024 OpenMPT Project Developers and Contributors\n"
|
"Copyright \xC2\xA9 2004-2025 OpenMPT Project Developers and Contributors\n"
|
||||||
"Copyright \xC2\xA9 1997-2003 Olivier Lapicque\n"
|
"Copyright \xC2\xA9 1997-2003 Olivier Lapicque\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Developers:\n"
|
"Developers:\n"
|
||||||
"Johannes Schultz (2008-2024)\n"
|
"Johannes Schultz (2008-2025)\n"
|
||||||
"J\xC3\xB6rn Heusipp (2012-2024)\n"
|
"J\xC3\xB6rn Heusipp (2012-2025)\n"
|
||||||
"Ahti Lepp\xC3\xA4nen (2005-2011)\n"
|
"Ahti Lepp\xC3\xA4nen (2005-2011)\n"
|
||||||
"Robin Fernandes (2004-2007)\n"
|
"Robin Fernandes (2004-2007)\n"
|
||||||
"Sergiy Pylypenko (2007)\n"
|
"Sergiy Pylypenko (2007)\n"
|
||||||
|
@ -803,7 +803,7 @@ mpt::ustring GetFullCreditsString()
|
||||||
mpt::ustring GetLicenseString()
|
mpt::ustring GetLicenseString()
|
||||||
{
|
{
|
||||||
return MPT_UTF8(
|
return MPT_UTF8(
|
||||||
"Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors" "\n"
|
"Copyright (c) 2004-2025, OpenMPT Project Developers and Contributors" "\n"
|
||||||
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
||||||
"All rights reserved." "\n"
|
"All rights reserved." "\n"
|
||||||
"" "\n"
|
"" "\n"
|
||||||
|
|
|
@ -17,7 +17,7 @@ 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 31
|
#define VER_MAJOR 31
|
||||||
#define VER_MINOR 13
|
#define VER_MINOR 14
|
||||||
#define VER_MINORMINOR 00
|
#define VER_MINORMINOR 00
|
||||||
|
|
||||||
OPENMPT_NAMESPACE_END
|
OPENMPT_NAMESPACE_END
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors
|
Copyright (c) 2004-2025, OpenMPT Project Developers and Contributors
|
||||||
Copyright (c) 1997-2003, Olivier Lapicque
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors
|
Copyright (c) 2004-2025, OpenMPT Project Developers and Contributors
|
||||||
Copyright (c) 1997-2003, Olivier Lapicque
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,9 @@ int main( int argc, char * argv[] ) {
|
||||||
file = fopen( argv[1], "rb" );
|
file = fopen( argv[1], "rb" );
|
||||||
#endif
|
#endif
|
||||||
mod = openmpt_module_create2( openmpt_stream_get_file_callbacks2(), file, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
mod = openmpt_module_create2( openmpt_stream_get_file_callbacks2(), file, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
|
||||||
|
#if defined( __clang__ ) && defined( __clang_analyzer__ )
|
||||||
|
[[clang::suppress]]
|
||||||
|
#endif
|
||||||
fclose( file );
|
fclose( file );
|
||||||
Pa_Initialize();
|
Pa_Initialize();
|
||||||
Pa_OpenDefaultStream( &stream, 0, 2, paInt16 | paNonInterleaved, SAMPLERATE, paFramesPerBufferUnspecified, NULL, NULL );
|
Pa_OpenDefaultStream( &stream, 0, 2, paInt16 | paNonInterleaved, SAMPLERATE, paFramesPerBufferUnspecified, NULL, NULL );
|
||||||
|
|
|
@ -223,7 +223,7 @@ static void config( HWND hwndParent ) {
|
||||||
static void about( HWND hwndParent ) {
|
static void about( HWND hwndParent ) {
|
||||||
std::ostringstream about;
|
std::ostringstream about;
|
||||||
about << SHORT_TITLE << " version " << openmpt::string::get( "library_version" ) << " " << "(built " << openmpt::string::get( "build" ) << ")" << std::endl;
|
about << SHORT_TITLE << " version " << openmpt::string::get( "library_version" ) << " " << "(built " << openmpt::string::get( "build" ) << ")" << std::endl;
|
||||||
about << " Copyright (c) 2013-2024 OpenMPT Project Developers and Contributors (https://lib.openmpt.org/)" << std::endl;
|
about << " Copyright (c) 2013-2025 OpenMPT Project Developers and Contributors (https://lib.openmpt.org/)" << std::endl;
|
||||||
about << " OpenMPT version " << openmpt::string::get( "core_version" ) << std::endl;
|
about << " OpenMPT version " << openmpt::string::get( "core_version" ) << std::endl;
|
||||||
about << std::endl;
|
about << std::endl;
|
||||||
about << openmpt::string::get( "contact" ) << std::endl;
|
about << openmpt::string::get( "contact" ) << std::endl;
|
||||||
|
|
|
@ -49,25 +49,25 @@
|
||||||
*
|
*
|
||||||
* libopenmpt can use 3 different strategies for file I/O.
|
* libopenmpt can use 3 different strategies for file I/O.
|
||||||
*
|
*
|
||||||
* - openmpt::module::module() with any kind of memory buffer as parameter will
|
|
||||||
* load the module from the provided memory buffer, which will require loading
|
|
||||||
* all data upfront by the library
|
|
||||||
* caller.
|
|
||||||
* - openmpt::module::module() with a seekable std::istream as parameter will
|
* - openmpt::module::module() with a seekable std::istream as parameter will
|
||||||
* load the module via the stream interface. libopenmpt will not implement an
|
* load the module via the stream interface. This is the recommended strategy.
|
||||||
* additional buffering layer in this case whih means the callbacks are assumed
|
|
||||||
* to be performant even with small i/o sizes.
|
|
||||||
* - openmpt::module::module() with an unseekable std::istream as parameter
|
* - openmpt::module::module() with an unseekable std::istream as parameter
|
||||||
* will load the module via the stream interface. libopempt will make an
|
* will load the module via the stream interface. libopempt will make an
|
||||||
* internal copy as it goes along, and sometimes have to pre-cache the whole
|
* internal copy as it goes along, and sometimes have to pre-cache the whole
|
||||||
* file in case it needs to know the complete file size. This strategy is
|
* file in case it needs to know the complete file size. This strategy is
|
||||||
* intended to be used if the file is located on a high latency network.
|
* intended to be used if the file is located on a high latency network.
|
||||||
|
* - openmpt::module::module() with any kind of memory buffer as parameter will
|
||||||
|
* load the module from the provided memory buffer, which will require loading
|
||||||
|
* all data upfront by the library caller. This strategy has the disadvantage of
|
||||||
|
* requiring all data to be loaded even when the module loading happens to fail
|
||||||
|
* after that. It should only be used when the data has already been loaded into
|
||||||
|
* memory for other reasons.
|
||||||
*
|
*
|
||||||
* | constructor | speed | memory consumption |
|
* | constructor | speed | memory consumption |
|
||||||
* | ----------------: | :----: | :----------------: |
|
* | ----------------: | :---: | :----------------: |
|
||||||
* | memory buffer | <p style="background-color:green" >fast </p> | <p style="background-color:yellow">medium</p> |
|
* | seekable stream | <p style="background-color:yellow">medium</p> | <p style="background-color:green" >low </p> |
|
||||||
* | seekable stream | <p style="background-color:red" >slow </p> | <p style="background-color:green" >low </p> |
|
|
||||||
* | unseekable stream | <p style="background-color:yellow">medium</p> | <p style="background-color:red" >high </p> |
|
* | unseekable stream | <p style="background-color:yellow">medium</p> | <p style="background-color:red" >high </p> |
|
||||||
|
* | memory buffer | <p style="background-color:green" >fast </p> | <p style="background-color:yellow">medium</p> |
|
||||||
*
|
*
|
||||||
* In all cases, the data or stream passed to the constructor is no longer
|
* In all cases, the data or stream passed to the constructor is no longer
|
||||||
* needed after the openmpt::module has been constructed and can be destroyed
|
* needed after the openmpt::module has been constructed and can be destroyed
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
/*! \brief libopenmpt minor version number */
|
/*! \brief libopenmpt minor version number */
|
||||||
#define OPENMPT_API_VERSION_MINOR 7
|
#define OPENMPT_API_VERSION_MINOR 7
|
||||||
/*! \brief libopenmpt patch version number */
|
/*! \brief libopenmpt patch version number */
|
||||||
#define OPENMPT_API_VERSION_PATCH 12
|
#define OPENMPT_API_VERSION_PATCH 13
|
||||||
/*! \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 */
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
LIBOPENMPT_VERSION_MAJOR=0
|
LIBOPENMPT_VERSION_MAJOR=0
|
||||||
LIBOPENMPT_VERSION_MINOR=7
|
LIBOPENMPT_VERSION_MINOR=7
|
||||||
LIBOPENMPT_VERSION_PATCH=12
|
LIBOPENMPT_VERSION_PATCH=13
|
||||||
LIBOPENMPT_VERSION_PREREL=
|
LIBOPENMPT_VERSION_PREREL=
|
||||||
|
|
||||||
LIBOPENMPT_LTVER_CURRENT=4
|
LIBOPENMPT_LTVER_CURRENT=4
|
||||||
LIBOPENMPT_LTVER_REVISION=12
|
LIBOPENMPT_LTVER_REVISION=13
|
||||||
LIBOPENMPT_LTVER_AGE=4
|
LIBOPENMPT_LTVER_AGE=4
|
||||||
|
|
|
@ -192,7 +192,7 @@ BEGIN
|
||||||
VALUE "FileDescription", VER_FILEDESC_STR
|
VALUE "FileDescription", VER_FILEDESC_STR
|
||||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||||
VALUE "InternalName", VER_FILENAME_STR
|
VALUE "InternalName", VER_FILENAME_STR
|
||||||
VALUE "LegalCopyright", "Copyright © 2004-2024 OpenMPT Project Developers and Contributors, Copyright © 1997-2003 Olivier Lapicque"
|
VALUE "LegalCopyright", "Copyright © 2004-2025 OpenMPT Project Developers and Contributors, Copyright © 1997-2003 Olivier Lapicque"
|
||||||
VALUE "OriginalFilename", VER_FILENAME_STR
|
VALUE "OriginalFilename", VER_FILENAME_STR
|
||||||
VALUE "ProductName", "libopenmpt"
|
VALUE "ProductName", "libopenmpt"
|
||||||
VALUE "ProductVersion", VER_FILEVERSION_STR
|
VALUE "ProductVersion", VER_FILEVERSION_STR
|
||||||
|
|
|
@ -46,7 +46,14 @@ static const char * xmp_openmpt_string = "OpenMPT (" OPENMPT_API_VERSION_STRING
|
||||||
|
|
||||||
#define USE_XMPLAY_ISTREAM
|
#define USE_XMPLAY_ISTREAM
|
||||||
|
|
||||||
|
// XMPLAY expects a WINAPI (which is __stdcall) function using an undecorated symbol name which conflicts with the provided declaration.
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#define XMPIN_GetInterface XMPIN_GetInterface_Dummy
|
||||||
|
#endif
|
||||||
#include "xmplay/xmpin.h"
|
#include "xmplay/xmpin.h"
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#undef XMPIN_GetInterface
|
||||||
|
#endif
|
||||||
|
|
||||||
// Shortcut block assigned to the OpenMPT plugin by un4seen.
|
// Shortcut block assigned to the OpenMPT plugin by un4seen.
|
||||||
enum {
|
enum {
|
||||||
|
@ -107,7 +114,9 @@ static void apply_and_save_options();
|
||||||
|
|
||||||
static std::string convert_to_native( const std::string & str );
|
static std::string convert_to_native( const std::string & str );
|
||||||
|
|
||||||
|
#if !defined(UNICODE)
|
||||||
static std::string StringEncode( const std::wstring &src, UINT codepage );
|
static std::string StringEncode( const std::wstring &src, UINT codepage );
|
||||||
|
#endif
|
||||||
|
|
||||||
static std::wstring StringDecode( const std::string & src, UINT codepage );
|
static std::wstring StringDecode( const std::string & src, UINT codepage );
|
||||||
|
|
||||||
|
@ -187,6 +196,7 @@ static std::string convert_to_native( const std::string & str ) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(UNICODE)
|
||||||
static std::string StringEncode( const std::wstring &src, UINT codepage )
|
static std::string StringEncode( const std::wstring &src, UINT codepage )
|
||||||
{
|
{
|
||||||
int required_size = WideCharToMultiByte( codepage, 0, src.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
int required_size = WideCharToMultiByte( codepage, 0, src.c_str(), -1, nullptr, 0, nullptr, nullptr);
|
||||||
|
@ -198,6 +208,7 @@ static std::string StringEncode( const std::wstring &src, UINT codepage )
|
||||||
WideCharToMultiByte( codepage, 0, src.c_str(), -1, encoded_string.data(), encoded_string.size(), nullptr, nullptr);
|
WideCharToMultiByte( codepage, 0, src.c_str(), -1, encoded_string.data(), encoded_string.size(), nullptr, nullptr);
|
||||||
return encoded_string.data();
|
return encoded_string.data();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static std::wstring StringDecode( const std::string & src, UINT codepage )
|
static std::wstring StringDecode( const std::string & src, UINT codepage )
|
||||||
{
|
{
|
||||||
|
@ -489,7 +500,7 @@ static void clear_current_timeinfo() {
|
||||||
static void WINAPI openmpt_About( HWND win ) {
|
static void WINAPI openmpt_About( HWND win ) {
|
||||||
std::ostringstream about;
|
std::ostringstream about;
|
||||||
about << SHORT_TITLE << " version " << openmpt::string::get( "library_version" ) << " " << "(built " << openmpt::string::get( "build" ) << ")" << std::endl;
|
about << SHORT_TITLE << " version " << openmpt::string::get( "library_version" ) << " " << "(built " << openmpt::string::get( "build" ) << ")" << std::endl;
|
||||||
about << " Copyright (c) 2013-2024 OpenMPT Project Developers and Contributors (https://lib.openmpt.org/)" << std::endl;
|
about << " Copyright (c) 2013-2025 OpenMPT Project Developers and Contributors (https://lib.openmpt.org/)" << std::endl;
|
||||||
about << " OpenMPT version " << openmpt::string::get( "core_version" ) << std::endl;
|
about << " OpenMPT version " << openmpt::string::get( "core_version" ) << std::endl;
|
||||||
about << std::endl;
|
about << std::endl;
|
||||||
about << openmpt::string::get( "contact" ) << std::endl;
|
about << openmpt::string::get( "contact" ) << std::endl;
|
||||||
|
@ -998,6 +1009,7 @@ static void WINAPI openmpt_SetFormat( XMPFORMAT * form ) {
|
||||||
form->rate = 0;
|
form->rate = 0;
|
||||||
form->chan = 0;
|
form->chan = 0;
|
||||||
form->res = 0;
|
form->res = 0;
|
||||||
|
form->chanmask = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( self->settings.samplerate != 0 ) {
|
if ( self->settings.samplerate != 0 ) {
|
||||||
|
@ -1026,6 +1038,7 @@ static void WINAPI openmpt_SetFormat( XMPFORMAT * form ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
form->res = 4; // float
|
form->res = 4; // float
|
||||||
|
form->chanmask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the tags
|
// get the tags
|
||||||
|
@ -1704,7 +1717,9 @@ static XMPIN xmpin = {
|
||||||
|
|
||||||
nullptr, // reserved2
|
nullptr, // reserved2
|
||||||
openmpt_GetConfig,
|
openmpt_GetConfig,
|
||||||
openmpt_SetConfig
|
openmpt_SetConfig,
|
||||||
|
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * xmp_openmpt_default_exts = "OpenMPT\0mptm/mptmz";
|
static const char * xmp_openmpt_default_exts = "OpenMPT\0mptm/mptmz";
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char * const license =
|
static const char * const license =
|
||||||
"Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors" "\n"
|
"Copyright (c) 2004-2025, OpenMPT Project Developers and Contributors" "\n"
|
||||||
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
"Copyright (c) 1997-2003, Olivier Lapicque" "\n"
|
||||||
"All rights reserved." "\n"
|
"All rights reserved." "\n"
|
||||||
"" "\n"
|
"" "\n"
|
||||||
|
@ -385,7 +385,7 @@ static void show_banner( concat_stream<mpt::ustring> & log, verbosity banner ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log << MPT_USTRING("openmpt123") << MPT_USTRING(" v") << mpt::transcode<mpt::ustring>( mpt::source_encoding, OPENMPT123_VERSION_STRING ) << MPT_USTRING(", libopenmpt ") << mpt::transcode<mpt::ustring>( libopenmpt_encoding, openmpt::string::get( "library_version" ) ) << MPT_USTRING(" (") << MPT_USTRING("OpenMPT ") << mpt::transcode<mpt::ustring>( libopenmpt_encoding, openmpt::string::get( "core_version" ) ) << MPT_USTRING(")") << lf;
|
log << MPT_USTRING("openmpt123") << MPT_USTRING(" v") << mpt::transcode<mpt::ustring>( mpt::source_encoding, OPENMPT123_VERSION_STRING ) << MPT_USTRING(", libopenmpt ") << mpt::transcode<mpt::ustring>( libopenmpt_encoding, openmpt::string::get( "library_version" ) ) << MPT_USTRING(" (") << MPT_USTRING("OpenMPT ") << mpt::transcode<mpt::ustring>( libopenmpt_encoding, openmpt::string::get( "core_version" ) ) << MPT_USTRING(")") << lf;
|
||||||
log << MPT_USTRING("Copyright (c) 2013-2024 OpenMPT Project Developers and Contributors <https://lib.openmpt.org/>") << lf;
|
log << MPT_USTRING("Copyright (c) 2013-2025 OpenMPT Project Developers and Contributors <https://lib.openmpt.org/>") << lf;
|
||||||
if ( banner == verbosity_normal ) {
|
if ( banner == verbosity_normal ) {
|
||||||
log << lf;
|
log << lf;
|
||||||
return;
|
return;
|
||||||
|
@ -462,7 +462,7 @@ static void show_banner( concat_stream<mpt::ustring> & log, verbosity banner ) {
|
||||||
static void show_man_version( textout & log ) {
|
static void show_man_version( textout & log ) {
|
||||||
log << MPT_USTRING("openmpt123") << MPT_USTRING(" v") << mpt::transcode<mpt::ustring>( mpt::source_encoding, OPENMPT123_VERSION_STRING ) << lf;
|
log << MPT_USTRING("openmpt123") << MPT_USTRING(" v") << mpt::transcode<mpt::ustring>( mpt::source_encoding, OPENMPT123_VERSION_STRING ) << lf;
|
||||||
log << lf;
|
log << lf;
|
||||||
log << MPT_USTRING("Copyright (c) 2013-2024 OpenMPT Project Developers and Contributors <https://lib.openmpt.org/>") << lf;
|
log << MPT_USTRING("Copyright (c) 2013-2025 OpenMPT Project Developers and Contributors <https://lib.openmpt.org/>") << lf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_short_version( textout & log ) {
|
static void show_short_version( textout & log ) {
|
||||||
|
|
|
@ -1415,7 +1415,13 @@ bool CDLSBank::Open(FileReader file)
|
||||||
uint32 nInsDef;
|
uint32 nInsDef;
|
||||||
|
|
||||||
if(file.GetOptionalFileName())
|
if(file.GetOptionalFileName())
|
||||||
|
{
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE)
|
||||||
|
m_szFileName = *(file.GetOptionalFileName());
|
||||||
|
#else
|
||||||
m_szFileName = file.GetOptionalFileName().value();
|
m_szFileName = file.GetOptionalFileName().value();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
file.Rewind();
|
file.Rewind();
|
||||||
if(!file.CanRead(256))
|
if(!file.CanRead(256))
|
||||||
|
|
|
@ -154,10 +154,11 @@ void ITCompression::CompressBlock(const typename Properties::sample_t *data, Smp
|
||||||
{
|
{
|
||||||
if(bwt[i] != width)
|
if(bwt[i] != width)
|
||||||
{
|
{
|
||||||
|
MPT_ASSERT(width >= 0);
|
||||||
if(width <= 6)
|
if(width <= 6)
|
||||||
{
|
{
|
||||||
// Mode A: 1 to 6 bits
|
// Mode A: 1 to 6 bits
|
||||||
MPT_ASSERT(width);
|
MPT_ASSERT(width != 0);
|
||||||
WriteBits(width, (1 << (width - 1)));
|
WriteBits(width, (1 << (width - 1)));
|
||||||
WriteBits(Properties::fetchA, ConvertWidth(width, bwt[i]));
|
WriteBits(Properties::fetchA, ConvertWidth(width, bwt[i]));
|
||||||
} else if(width < Properties::defWidth)
|
} else if(width < Properties::defWidth)
|
||||||
|
|
|
@ -483,6 +483,42 @@ void CSoundFile::WriteInstrumentPropertyForAllInstruments(uint32 code, uint16 si
|
||||||
#endif // !MODPLUG_NO_FILESAVE
|
#endif // !MODPLUG_NO_FILESAVE
|
||||||
|
|
||||||
|
|
||||||
|
// Convert instrument flags which were read from 'dF..' extension to proper internal representation.
|
||||||
|
static void ConvertInstrumentFlags(ModInstrument &ins, uint32 flags)
|
||||||
|
{
|
||||||
|
ins.VolEnv.dwFlags.set(ENV_ENABLED, (flags & 0x0001) != 0);
|
||||||
|
ins.VolEnv.dwFlags.set(ENV_SUSTAIN, (flags & 0x0002) != 0);
|
||||||
|
ins.VolEnv.dwFlags.set(ENV_LOOP, (flags & 0x0004) != 0);
|
||||||
|
ins.VolEnv.dwFlags.set(ENV_CARRY, (flags & 0x0800) != 0);
|
||||||
|
|
||||||
|
ins.PanEnv.dwFlags.set(ENV_ENABLED, (flags & 0x0008) != 0);
|
||||||
|
ins.PanEnv.dwFlags.set(ENV_SUSTAIN, (flags & 0x0010) != 0);
|
||||||
|
ins.PanEnv.dwFlags.set(ENV_LOOP, (flags & 0x0020) != 0);
|
||||||
|
ins.PanEnv.dwFlags.set(ENV_CARRY, (flags & 0x1000) != 0);
|
||||||
|
|
||||||
|
ins.PitchEnv.dwFlags.set(ENV_ENABLED, (flags & 0x0040) != 0);
|
||||||
|
ins.PitchEnv.dwFlags.set(ENV_SUSTAIN, (flags & 0x0080) != 0);
|
||||||
|
ins.PitchEnv.dwFlags.set(ENV_LOOP, (flags & 0x0100) != 0);
|
||||||
|
ins.PitchEnv.dwFlags.set(ENV_CARRY, (flags & 0x2000) != 0);
|
||||||
|
ins.PitchEnv.dwFlags.set(ENV_FILTER, (flags & 0x0400) != 0);
|
||||||
|
|
||||||
|
ins.dwFlags.set(INS_SETPANNING, (flags & 0x0200) != 0);
|
||||||
|
ins.dwFlags.set(INS_MUTE, (flags & 0x4000) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Convert VFLG / PFLG / AFLG
|
||||||
|
static void ConvertEnvelopeFlags(ModInstrument &instr, uint32 flags, EnvelopeType envType)
|
||||||
|
{
|
||||||
|
InstrumentEnvelope &env = instr.GetEnvelope(envType);
|
||||||
|
env.dwFlags.set(ENV_ENABLED, (flags & 0x01) != 0);
|
||||||
|
env.dwFlags.set(ENV_LOOP, (flags & 0x02) != 0);
|
||||||
|
env.dwFlags.set(ENV_SUSTAIN, (flags & 0x04) != 0);
|
||||||
|
env.dwFlags.set(ENV_CARRY, (flags & 0x08) != 0);
|
||||||
|
env.dwFlags.set(ENV_FILTER, (envType == ENV_PITCH) && (flags & 0x10) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
// Convenient macro to help GET_HEADER declaration for single type members ONLY (non-array)
|
// Convenient macro to help GET_HEADER declaration for single type members ONLY (non-array)
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
@ -569,7 +605,6 @@ bool ReadInstrumentHeaderField(ModInstrument *input, uint32 fcode, uint16 fsize,
|
||||||
{
|
{
|
||||||
// clang-format off
|
// clang-format off
|
||||||
GET_MPTHEADER_sized_member( nFadeOut , uint32 , MagicBE("FO..") )
|
GET_MPTHEADER_sized_member( nFadeOut , uint32 , MagicBE("FO..") )
|
||||||
GET_MPTHEADER_sized_member( dwFlags , uint8 , MagicBE("dF..") )
|
|
||||||
GET_MPTHEADER_sized_member( nGlobalVol , uint32 , MagicBE("GV..") )
|
GET_MPTHEADER_sized_member( nGlobalVol , uint32 , MagicBE("GV..") )
|
||||||
GET_MPTHEADER_sized_member( nPan , uint32 , MagicBE("P...") )
|
GET_MPTHEADER_sized_member( nPan , uint32 , MagicBE("P...") )
|
||||||
GET_MPTHEADER_sized_member( VolEnv.nLoopStart , uint8 , MagicBE("VLS.") )
|
GET_MPTHEADER_sized_member( VolEnv.nLoopStart , uint8 , MagicBE("VLS.") )
|
||||||
|
@ -616,11 +651,20 @@ bool ReadInstrumentHeaderField(ModInstrument *input, uint32 fcode, uint16 fsize,
|
||||||
GET_MPTHEADER_sized_member( PitchEnv.nReleaseNode , uint8 , MagicBE("PERN") )
|
GET_MPTHEADER_sized_member( PitchEnv.nReleaseNode , uint8 , MagicBE("PERN") )
|
||||||
GET_MPTHEADER_sized_member( PanEnv.nReleaseNode , uint8 , MagicBE("AERN") )
|
GET_MPTHEADER_sized_member( PanEnv.nReleaseNode , uint8 , MagicBE("AERN") )
|
||||||
GET_MPTHEADER_sized_member( VolEnv.nReleaseNode , uint8 , MagicBE("VERN") )
|
GET_MPTHEADER_sized_member( VolEnv.nReleaseNode , uint8 , MagicBE("VERN") )
|
||||||
GET_MPTHEADER_sized_member( PitchEnv.dwFlags , uint8 , MagicBE("PFLG") )
|
|
||||||
GET_MPTHEADER_sized_member( PanEnv.dwFlags , uint8 , MagicBE("AFLG") )
|
|
||||||
GET_MPTHEADER_sized_member( VolEnv.dwFlags , uint8 , MagicBE("VFLG") )
|
|
||||||
GET_MPTHEADER_sized_member( midiPWD , int8 , MagicBE("MPWD") )
|
GET_MPTHEADER_sized_member( midiPWD , int8 , MagicBE("MPWD") )
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
case MagicBE("dF.."):
|
||||||
|
ConvertInstrumentFlags(*input, file.ReadSizedIntLE<uint32>(fsize));
|
||||||
|
return true;
|
||||||
|
case MagicBE("VFLG"):
|
||||||
|
ConvertEnvelopeFlags(*input, file.ReadSizedIntLE<uint32>(fsize), ENV_VOLUME);
|
||||||
|
return true;
|
||||||
|
case MagicBE("AFLG"):
|
||||||
|
ConvertEnvelopeFlags(*input, file.ReadSizedIntLE<uint32>(fsize), ENV_PANNING);
|
||||||
|
return true;
|
||||||
|
case MagicBE("PFLG"):
|
||||||
|
ConvertEnvelopeFlags(*input, file.ReadSizedIntLE<uint32>(fsize), ENV_PITCH);
|
||||||
|
return true;
|
||||||
case MagicBE("R..."):
|
case MagicBE("R..."):
|
||||||
{
|
{
|
||||||
// Resampling has been written as various sizes including uint16 and uint32 in the past
|
// Resampling has been written as various sizes including uint16 and uint32 in the past
|
||||||
|
@ -660,54 +704,6 @@ bool ReadInstrumentHeaderField(ModInstrument *input, uint32 fcode, uint16 fsize,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Convert instrument flags which were read from 'dF..' extension to proper internal representation.
|
|
||||||
static void ConvertReadExtendedFlags(ModInstrument *pIns)
|
|
||||||
{
|
|
||||||
// Flags of 'dF..' datafield in extended instrument properties.
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
dFdd_VOLUME = 0x0001,
|
|
||||||
dFdd_VOLSUSTAIN = 0x0002,
|
|
||||||
dFdd_VOLLOOP = 0x0004,
|
|
||||||
dFdd_PANNING = 0x0008,
|
|
||||||
dFdd_PANSUSTAIN = 0x0010,
|
|
||||||
dFdd_PANLOOP = 0x0020,
|
|
||||||
dFdd_PITCH = 0x0040,
|
|
||||||
dFdd_PITCHSUSTAIN = 0x0080,
|
|
||||||
dFdd_PITCHLOOP = 0x0100,
|
|
||||||
dFdd_SETPANNING = 0x0200,
|
|
||||||
dFdd_FILTER = 0x0400,
|
|
||||||
dFdd_VOLCARRY = 0x0800,
|
|
||||||
dFdd_PANCARRY = 0x1000,
|
|
||||||
dFdd_PITCHCARRY = 0x2000,
|
|
||||||
dFdd_MUTE = 0x4000,
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32 dwOldFlags = pIns->dwFlags.GetRaw();
|
|
||||||
|
|
||||||
pIns->VolEnv.dwFlags.set(ENV_ENABLED, (dwOldFlags & dFdd_VOLUME) != 0);
|
|
||||||
pIns->VolEnv.dwFlags.set(ENV_SUSTAIN, (dwOldFlags & dFdd_VOLSUSTAIN) != 0);
|
|
||||||
pIns->VolEnv.dwFlags.set(ENV_LOOP, (dwOldFlags & dFdd_VOLLOOP) != 0);
|
|
||||||
pIns->VolEnv.dwFlags.set(ENV_CARRY, (dwOldFlags & dFdd_VOLCARRY) != 0);
|
|
||||||
|
|
||||||
pIns->PanEnv.dwFlags.set(ENV_ENABLED, (dwOldFlags & dFdd_PANNING) != 0);
|
|
||||||
pIns->PanEnv.dwFlags.set(ENV_SUSTAIN, (dwOldFlags & dFdd_PANSUSTAIN) != 0);
|
|
||||||
pIns->PanEnv.dwFlags.set(ENV_LOOP, (dwOldFlags & dFdd_PANLOOP) != 0);
|
|
||||||
pIns->PanEnv.dwFlags.set(ENV_CARRY, (dwOldFlags & dFdd_PANCARRY) != 0);
|
|
||||||
|
|
||||||
pIns->PitchEnv.dwFlags.set(ENV_ENABLED, (dwOldFlags & dFdd_PITCH) != 0);
|
|
||||||
pIns->PitchEnv.dwFlags.set(ENV_SUSTAIN, (dwOldFlags & dFdd_PITCHSUSTAIN) != 0);
|
|
||||||
pIns->PitchEnv.dwFlags.set(ENV_LOOP, (dwOldFlags & dFdd_PITCHLOOP) != 0);
|
|
||||||
pIns->PitchEnv.dwFlags.set(ENV_CARRY, (dwOldFlags & dFdd_PITCHCARRY) != 0);
|
|
||||||
pIns->PitchEnv.dwFlags.set(ENV_FILTER, (dwOldFlags & dFdd_FILTER) != 0);
|
|
||||||
|
|
||||||
pIns->dwFlags.reset();
|
|
||||||
pIns->dwFlags.set(INS_SETPANNING, (dwOldFlags & dFdd_SETPANNING) != 0);
|
|
||||||
pIns->dwFlags.set(INS_MUTE, (dwOldFlags & dFdd_MUTE) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ReadInstrumentExtensionField(ModInstrument* pIns, const uint32 code, const uint16 size, FileReader &file)
|
void ReadInstrumentExtensionField(ModInstrument* pIns, const uint32 code, const uint16 size, FileReader &file)
|
||||||
{
|
{
|
||||||
if(code == MagicBE("K[.."))
|
if(code == MagicBE("K[.."))
|
||||||
|
@ -724,9 +720,6 @@ void ReadInstrumentExtensionField(ModInstrument* pIns, const uint32 code, const
|
||||||
file.Skip(size);
|
file.Skip(size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code == MagicBE("dF..")) // 'dF..' field requires additional processing.
|
|
||||||
ConvertReadExtendedFlags(pIns);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -261,7 +261,7 @@ bool CSoundFile::ReadITP(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
if(const auto fileName = file.GetOptionalFileName(); fileName.has_value())
|
if(const auto fileName = file.GetOptionalFileName(); fileName.has_value())
|
||||||
{
|
{
|
||||||
instrPaths[ins] = mpt::AbsolutePathToRelative(instrPaths[ins], fileName->GetDirectoryWithDrive());
|
instrPaths[ins] = mpt::RelativePathToAbsolute(instrPaths[ins], fileName->GetDirectoryWithDrive());
|
||||||
} else if(GetpModDoc() != nullptr)
|
} else if(GetpModDoc() != nullptr)
|
||||||
{
|
{
|
||||||
instrPaths[ins] = mpt::RelativePathToAbsolute(instrPaths[ins], GetpModDoc()->GetPathNameMpt().GetDirectoryWithDrive());
|
instrPaths[ins] = mpt::RelativePathToAbsolute(instrPaths[ins], GetpModDoc()->GetPathNameMpt().GetDirectoryWithDrive());
|
||||||
|
@ -309,15 +309,13 @@ bool CSoundFile::ReadITP(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
|
|
||||||
// Pattern data
|
// Pattern data
|
||||||
size_t numCommands = GetNumChannels() * numRows;
|
size_t numCommands = GetNumChannels() * numRows;
|
||||||
|
|
||||||
if(patternChunk.CanRead(sizeof(ITPModCommand) * numCommands))
|
if(patternChunk.CanRead(sizeof(ITPModCommand) * numCommands))
|
||||||
{
|
{
|
||||||
ModCommand *target = Patterns[pat].GetpModCommand(0, 0);
|
for(ModCommand &m : Patterns[pat])
|
||||||
while(numCommands-- != 0)
|
|
||||||
{
|
{
|
||||||
ITPModCommand data;
|
ITPModCommand data;
|
||||||
patternChunk.ReadStruct(data);
|
patternChunk.ReadStruct(data);
|
||||||
*(target++) = data;
|
m = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +328,7 @@ bool CSoundFile::ReadITP(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
|
|
||||||
// Read number of embedded samples - at most as many as there are real samples in a valid file
|
// Read number of embedded samples - at most as many as there are real samples in a valid file
|
||||||
uint32 embeddedSamples = file.ReadUint32LE();
|
uint32 embeddedSamples = file.ReadUint32LE();
|
||||||
if(embeddedSamples > m_nSamples)
|
if(embeddedSamples > GetNumSamples())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1016,7 +1016,7 @@ bool CSoundFile::ReadMO3(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
CMD_PORTAMENTOUP, CMD_TREMOR, CMD_RETRIG, CMD_FINEVIBRATO,
|
CMD_PORTAMENTOUP, CMD_TREMOR, CMD_RETRIG, CMD_FINEVIBRATO,
|
||||||
CMD_CHANNELVOLUME, CMD_CHANNELVOLSLIDE, CMD_PANNINGSLIDE, CMD_S3MCMDEX,
|
CMD_CHANNELVOLUME, CMD_CHANNELVOLSLIDE, CMD_PANNINGSLIDE, CMD_S3MCMDEX,
|
||||||
CMD_TEMPO, CMD_GLOBALVOLSLIDE, CMD_PANBRELLO, CMD_MIDI,
|
CMD_TEMPO, CMD_GLOBALVOLSLIDE, CMD_PANBRELLO, CMD_MIDI,
|
||||||
CMD_NONE,/*FineVolSld*/ CMD_NONE,/*PortaDown*/ CMD_NONE, /*PortaUp*/ CMD_NONE,
|
CMD_NONE,/*FineVolSld*/ CMD_NONE,/*PortaDown*/ CMD_NONE, /*PortaUp*/ CMD_DUMMY,
|
||||||
CMD_NONE,/*ITVolCol*/ CMD_XPARAM, CMD_SMOOTHMIDI, CMD_DELAYCUT,
|
CMD_NONE,/*ITVolCol*/ CMD_XPARAM, CMD_SMOOTHMIDI, CMD_DELAYCUT,
|
||||||
CMD_FINETUNE, CMD_FINETUNE_SMOOTH,
|
CMD_FINETUNE, CMD_FINETUNE_SMOOTH,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1286,7 +1286,11 @@ bool CSoundFile::ReadMOD(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
FileReader amData;
|
FileReader amData;
|
||||||
if(file.GetOptionalFileName())
|
if(file.GetOptionalFileName())
|
||||||
{
|
{
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE)
|
||||||
|
mpt::PathString filename = *(file.GetOptionalFileName());
|
||||||
|
#else
|
||||||
mpt::PathString filename = file.GetOptionalFileName().value();
|
mpt::PathString filename = file.GetOptionalFileName().value();
|
||||||
|
#endif
|
||||||
// Find instrument definition file
|
// Find instrument definition file
|
||||||
const mpt::PathString exts[] = {P_(".nt"), P_(".NT"), P_(".as"), P_(".AS")};
|
const mpt::PathString exts[] = {P_(".nt"), P_(".NT"), P_(".as"), P_(".AS")};
|
||||||
for(const auto &ext : exts)
|
for(const auto &ext : exts)
|
||||||
|
|
|
@ -679,9 +679,10 @@ bool CSoundFile::ReadXM(FileReader &file, ModLoadingFlags loadFlags)
|
||||||
m_playBehaviour.reset(kFT2ST3OffsetOutOfRange);
|
m_playBehaviour.reset(kFT2ST3OffsetOutOfRange);
|
||||||
// Fix arpeggios in KAPTENFL.XM
|
// Fix arpeggios in KAPTENFL.XM
|
||||||
m_playBehaviour.reset(kFT2Arpeggio);
|
m_playBehaviour.reset(kFT2Arpeggio);
|
||||||
} else if(!memcmp(fileHeader.trackerName, "*Converted ", 11))
|
} else if(!memcmp(fileHeader.trackerName, "*Converted ", 11) && !memcmp(fileHeader.trackerName + 14, "-File*", 6))
|
||||||
{
|
{
|
||||||
madeWith = verDigiTrakker;
|
madeWith = verDigiTrakker | verConfirmed;
|
||||||
|
madeWithTracker = UL_("Digitrakker");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1389,9 +1390,11 @@ bool CSoundFile::SaveXM(std::ostream &f, bool compatibilityExport)
|
||||||
if(Instruments[ins] != nullptr)
|
if(Instruments[ins] != nullptr)
|
||||||
{
|
{
|
||||||
// Convert instrument
|
// Convert instrument
|
||||||
insHeader.ConvertToXM(*Instruments[ins], compatibilityExport);
|
auto sampleList = insHeader.ConvertToXM(*Instruments[ins], compatibilityExport);
|
||||||
|
samples = std::move(sampleList.samples);
|
||||||
|
if(sampleList.tooManySamples)
|
||||||
|
AddToLog(LogInformation, MPT_UFORMAT("Instrument {} references too many samples, only the first {} will be exported.")(ins, samples.size()));
|
||||||
|
|
||||||
samples = insHeader.instrument.GetSampleList(*Instruments[ins], compatibilityExport);
|
|
||||||
if(samples.size() > 0 && samples[0] <= GetNumSamples())
|
if(samples.size() > 0 && samples[0] <= GetNumSamples())
|
||||||
{
|
{
|
||||||
// Copy over auto-vibrato settings of first sample
|
// Copy over auto-vibrato settings of first sample
|
||||||
|
|
|
@ -144,6 +144,10 @@ struct ModSample
|
||||||
void SetLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile);
|
void SetLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile);
|
||||||
// Set sustain loop points and update loop wrap-around buffer
|
// Set sustain loop points and update loop wrap-around buffer
|
||||||
void SetSustainLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile);
|
void SetSustainLoop(SmpLength start, SmpLength end, bool enable, bool pingpong, CSoundFile &sndFile);
|
||||||
|
// Retrieve the normal loop points
|
||||||
|
std::pair<SmpLength, SmpLength> GetLoop() const noexcept { return std::make_pair(nLoopStart, nLoopEnd); }
|
||||||
|
// Retrieve the sustain loop points
|
||||||
|
std::pair<SmpLength, SmpLength> GetSustainLoop() const noexcept { return std::make_pair(nSustainStart, nSustainEnd); }
|
||||||
// Update loop wrap-around buffer
|
// Update loop wrap-around buffer
|
||||||
void PrecomputeLoops(CSoundFile &sndFile, bool updateChannels = true);
|
void PrecomputeLoops(CSoundFile &sndFile, bool updateChannels = true);
|
||||||
|
|
||||||
|
|
|
@ -1360,9 +1360,11 @@ bool CSoundFile::SaveXIInstrument(INSTRUMENTINDEX nInstr, std::ostream &f) const
|
||||||
|
|
||||||
// Create file header
|
// Create file header
|
||||||
XIInstrumentHeader header;
|
XIInstrumentHeader header;
|
||||||
header.ConvertToXM(*pIns, false);
|
const auto sampleList = header.ConvertToXM(*pIns, false);
|
||||||
|
const auto &samples = sampleList.samples;
|
||||||
|
if(sampleList.tooManySamples)
|
||||||
|
AddToLog(LogInformation, MPT_UFORMAT("This instrument references too many samples, only the first {} will be exported.")(samples.size()));
|
||||||
|
|
||||||
const std::vector<SAMPLEINDEX> samples = header.instrument.GetSampleList(*pIns, false);
|
|
||||||
if(samples.size() > 0 && samples[0] <= GetNumSamples())
|
if(samples.size() > 0 && samples[0] <= GetNumSamples())
|
||||||
{
|
{
|
||||||
// Copy over auto-vibrato settings of first sample
|
// Copy over auto-vibrato settings of first sample
|
||||||
|
|
|
@ -42,8 +42,12 @@ using SmpLength = uint32;
|
||||||
|
|
||||||
inline constexpr SmpLength MAX_SAMPLE_LENGTH = 0x10000000; // Sample length in frames. Sample size in bytes can be more than this (= 256 MB).
|
inline constexpr SmpLength MAX_SAMPLE_LENGTH = 0x10000000; // Sample length in frames. Sample size in bytes can be more than this (= 256 MB).
|
||||||
|
|
||||||
|
inline constexpr ROWINDEX MAX_ROWS_PER_MEASURE = 65536;
|
||||||
|
inline constexpr ROWINDEX MAX_ROWS_PER_BEAT = 65536;
|
||||||
|
inline constexpr ROWINDEX DEFAULT_ROWS_PER_BEAT = 4;
|
||||||
|
inline constexpr ROWINDEX DEFAULT_ROWS_PER_MEASURE = 16;
|
||||||
|
|
||||||
inline constexpr ROWINDEX MAX_PATTERN_ROWS = 1024;
|
inline constexpr ROWINDEX MAX_PATTERN_ROWS = 1024;
|
||||||
inline constexpr ROWINDEX MAX_ROWS_PER_BEAT = 65536;
|
|
||||||
inline constexpr ORDERINDEX MAX_ORDERS = ORDERINDEX_MAX + 1;
|
inline constexpr ORDERINDEX MAX_ORDERS = ORDERINDEX_MAX + 1;
|
||||||
inline constexpr PATTERNINDEX MAX_PATTERNS = 4000;
|
inline constexpr PATTERNINDEX MAX_PATTERNS = 4000;
|
||||||
inline constexpr SAMPLEINDEX MAX_SAMPLES = 4000;
|
inline constexpr SAMPLEINDEX MAX_SAMPLES = 4000;
|
||||||
|
|
|
@ -1391,7 +1391,10 @@ void CSoundFile::InstrumentChange(ModChannel &chn, uint32 instr, bool bPorta, bo
|
||||||
|
|
||||||
if(pIns->NoteMap[note - NOTE_MIN] > NOTE_MAX) return;
|
if(pIns->NoteMap[note - NOTE_MIN] > NOTE_MAX) return;
|
||||||
uint32 n = pIns->Keyboard[note - NOTE_MIN];
|
uint32 n = pIns->Keyboard[note - NOTE_MIN];
|
||||||
pSmp = (n <= GetNumSamples()) ? &Samples[n] : &Samples[0];
|
if(n)
|
||||||
|
pSmp = (n <= GetNumSamples()) ? &Samples[n] : &Samples[0];
|
||||||
|
else
|
||||||
|
pSmp = nullptr;
|
||||||
} else if(GetNumInstruments())
|
} else if(GetNumInstruments())
|
||||||
{
|
{
|
||||||
// No valid instrument, or not a valid note.
|
// No valid instrument, or not a valid note.
|
||||||
|
@ -2129,19 +2132,22 @@ CHANNELINDEX CSoundFile::GetNNAChannel(CHANNELINDEX nChn) const
|
||||||
for(CHANNELINDEX i = m_nChannels; i < MAX_CHANNELS; i++)
|
for(CHANNELINDEX i = m_nChannels; i < MAX_CHANNELS; i++)
|
||||||
{
|
{
|
||||||
const ModChannel &c = m_PlayState.Chn[i];
|
const ModChannel &c = m_PlayState.Chn[i];
|
||||||
// No sample and no plugin playing
|
// Sample playing?
|
||||||
if(!c.nLength && !c.HasMIDIOutput())
|
if(c.nLength)
|
||||||
|
continue;
|
||||||
|
// Can a plugin potentially be playing?
|
||||||
|
if(!c.HasMIDIOutput())
|
||||||
return i;
|
return i;
|
||||||
// Plugin channel with already released note
|
// Has the plugin note already been released? (note: lastMidiNoteWithoutArp is set from within IMixPlugin, so this implies that there is a valid plugin assignment)
|
||||||
if(!c.nLength && c.dwFlags[CHN_KEYOFF | CHN_NOTEFADE])
|
if(c.dwFlags[CHN_KEYOFF | CHN_NOTEFADE] || c.lastMidiNoteWithoutArp == NOTE_NONE)
|
||||||
return i;
|
return i;
|
||||||
// Stopped OPL channel
|
// Stopped OPL channel
|
||||||
if(c.dwFlags[CHN_ADLIB] && (!m_opl || !m_opl->IsActive(i)))
|
if(c.dwFlags[CHN_ADLIB] && (!m_opl || !m_opl->IsActive(i)))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 vol = 0x800000;
|
int32 vol = 0x800100;
|
||||||
if(nChn < MAX_CHANNELS)
|
if(nChn < m_PlayState.Chn.size())
|
||||||
{
|
{
|
||||||
const ModChannel &srcChn = m_PlayState.Chn[nChn];
|
const ModChannel &srcChn = m_PlayState.Chn[nChn];
|
||||||
if(!srcChn.nFadeOutVol && srcChn.nLength)
|
if(!srcChn.nFadeOutVol && srcChn.nLength)
|
||||||
|
@ -2160,7 +2166,8 @@ CHANNELINDEX CSoundFile::GetNNAChannel(CHANNELINDEX nChn) const
|
||||||
// Use a combination of real volume [14 bit] (which includes volume envelopes, but also potentially global volume) and note volume [9 bit].
|
// Use a combination of real volume [14 bit] (which includes volume envelopes, but also potentially global volume) and note volume [9 bit].
|
||||||
// Rationale: We need volume envelopes in case e.g. all NNA channels are playing at full volume but are looping on a 0-volume envelope node.
|
// Rationale: We need volume envelopes in case e.g. all NNA channels are playing at full volume but are looping on a 0-volume envelope node.
|
||||||
// But if global volume is not applied to master and the global volume temporarily drops to 0, we would kill arbitrary channels. Hence, add the note volume as well.
|
// But if global volume is not applied to master and the global volume temporarily drops to 0, we would kill arbitrary channels. Hence, add the note volume as well.
|
||||||
uint32 v = (c.nRealVolume << 9) | c.nVolume;
|
int32 v = (c.nRealVolume << 9) | c.nVolume;
|
||||||
|
// Less priority to looped samples
|
||||||
if(c.dwFlags[CHN_LOOP])
|
if(c.dwFlags[CHN_LOOP])
|
||||||
v /= 2;
|
v /= 2;
|
||||||
if((v < vol) || ((v == vol) && (c.VolEnv.nEnvPosition > envpos)))
|
if((v < vol) || ((v == vol) && (c.VolEnv.nEnvPosition > envpos)))
|
||||||
|
@ -5165,6 +5172,12 @@ void CSoundFile::ParseMIDIMacro(PlayState &playState, CHANNELINDEX nChn, bool is
|
||||||
} else if(macro[pos] == 's')
|
} else if(macro[pos] == 's')
|
||||||
{
|
{
|
||||||
// SysEx Checksum (not an original Impulse Tracker macro variable, but added for convenience)
|
// SysEx Checksum (not an original Impulse Tracker macro variable, but added for convenience)
|
||||||
|
if(!firstNibble) // From MIDI.TXT: '9n' is exactly the same as '09 n' or '9 n' -- so finish current byte first
|
||||||
|
{
|
||||||
|
outPos++;
|
||||||
|
firstNibble = true;
|
||||||
|
}
|
||||||
|
|
||||||
auto startPos = outPos;
|
auto startPos = outPos;
|
||||||
while(startPos > 0 && out[--startPos] != 0xF0)
|
while(startPos > 0 && out[--startPos] != 0xF0)
|
||||||
;
|
;
|
||||||
|
@ -6063,7 +6076,7 @@ void CSoundFile::PatternLoop(PlayState &state, CHANNELINDEX nChn, ModCommand::PA
|
||||||
// IT compatibility 10. Pattern loops (+ same fix for XM / MOD / S3M files)
|
// IT compatibility 10. Pattern loops (+ same fix for XM / MOD / S3M files)
|
||||||
if(!m_playBehaviour[kITFT2PatternLoop] && !(GetType() & (MOD_TYPE_MOD | MOD_TYPE_S3M)))
|
if(!m_playBehaviour[kITFT2PatternLoop] && !(GetType() & (MOD_TYPE_MOD | MOD_TYPE_S3M)))
|
||||||
{
|
{
|
||||||
auto p = std::cbegin(state.Chn);
|
auto p = state.Chn.data();
|
||||||
for(CHANNELINDEX i = 0; i < GetNumChannels(); i++, p++)
|
for(CHANNELINDEX i = 0; i < GetNumChannels(); i++, p++)
|
||||||
{
|
{
|
||||||
// Loop on other channel
|
// Loop on other channel
|
||||||
|
@ -6289,6 +6302,8 @@ uint32 CSoundFile::GetFreqFromPeriod(uint32 period, uint32 c5speed, int32 nPerio
|
||||||
octave = ((14 - div) & 0x1F);
|
octave = ((14 - div) & 0x1F);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
if(period > 29 * 768)
|
||||||
|
return 0;
|
||||||
octave = (period / 768) + 2;
|
octave = (period / 768) + 2;
|
||||||
}
|
}
|
||||||
return (XMLinearTable[period % 768] << (FREQ_FRACBITS + 2)) >> octave;
|
return (XMLinearTable[period % 768] << (FREQ_FRACBITS + 2)) >> octave;
|
||||||
|
|
|
@ -136,11 +136,11 @@ CSoundFile::CSoundFile() :
|
||||||
#ifdef MODPLUG_TRACKER
|
#ifdef MODPLUG_TRACKER
|
||||||
m_bChannelMuteTogglePending.reset();
|
m_bChannelMuteTogglePending.reset();
|
||||||
|
|
||||||
m_nDefaultRowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat = (TrackerSettings::Instance().m_nRowHighlightBeats) ? TrackerSettings::Instance().m_nRowHighlightBeats : 4;
|
m_nDefaultRowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat = (TrackerSettings::Instance().m_nRowHighlightBeats) ? TrackerSettings::Instance().m_nRowHighlightBeats : DEFAULT_ROWS_PER_BEAT;
|
||||||
m_nDefaultRowsPerMeasure = m_PlayState.m_nCurrentRowsPerMeasure = (TrackerSettings::Instance().m_nRowHighlightMeasures >= m_nDefaultRowsPerBeat) ? TrackerSettings::Instance().m_nRowHighlightMeasures : m_nDefaultRowsPerBeat * 4;
|
m_nDefaultRowsPerMeasure = m_PlayState.m_nCurrentRowsPerMeasure = (TrackerSettings::Instance().m_nRowHighlightMeasures >= m_nDefaultRowsPerBeat) ? TrackerSettings::Instance().m_nRowHighlightMeasures : m_nDefaultRowsPerBeat * 4;
|
||||||
#else
|
#else
|
||||||
m_nDefaultRowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat = 4;
|
m_nDefaultRowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat = DEFAULT_ROWS_PER_BEAT;
|
||||||
m_nDefaultRowsPerMeasure = m_PlayState.m_nCurrentRowsPerMeasure = 16;
|
m_nDefaultRowsPerMeasure = m_PlayState.m_nCurrentRowsPerMeasure = DEFAULT_ROWS_PER_MEASURE;
|
||||||
#endif // MODPLUG_TRACKER
|
#endif // MODPLUG_TRACKER
|
||||||
|
|
||||||
MemsetZero(Instruments);
|
MemsetZero(Instruments);
|
||||||
|
@ -212,6 +212,7 @@ void CSoundFile::InitializeGlobals(MODTYPE type)
|
||||||
m_nResampling = SRCMODE_DEFAULT;
|
m_nResampling = SRCMODE_DEFAULT;
|
||||||
m_dwLastSavedWithVersion = Version(0);
|
m_dwLastSavedWithVersion = Version(0);
|
||||||
m_dwCreatedWithVersion = Version(0);
|
m_dwCreatedWithVersion = Version(0);
|
||||||
|
m_nTempoMode = TempoMode::Classic;
|
||||||
|
|
||||||
SetMixLevels(MixLevels::Compatible);
|
SetMixLevels(MixLevels::Compatible);
|
||||||
|
|
||||||
|
@ -880,11 +881,12 @@ double CSoundFile::GetCurrentBPM() const
|
||||||
bpm = m_PlayState.m_nMusicTempo.ToDouble();
|
bpm = m_PlayState.m_nMusicTempo.ToDouble();
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
//with other modes, we calculate it:
|
// With other modes, we calculate it:
|
||||||
double ticksPerBeat = m_PlayState.m_nMusicSpeed * m_PlayState.m_nCurrentRowsPerBeat; //ticks/beat = ticks/row * rows/beat
|
ROWINDEX rowsPerBeat = m_PlayState.m_nCurrentRowsPerBeat ? m_PlayState.m_nCurrentRowsPerBeat : DEFAULT_ROWS_PER_BEAT;
|
||||||
double samplesPerBeat = m_PlayState.m_nSamplesPerTick * ticksPerBeat; //samps/beat = samps/tick * ticks/beat
|
double ticksPerBeat = m_PlayState.m_nMusicSpeed * rowsPerBeat; // Ticks/beat = ticks/row * rows/beat
|
||||||
bpm = m_MixerSettings.gdwMixingFreq / samplesPerBeat * 60; //beats/sec = samps/sec / samps/beat
|
double samplesPerBeat = m_PlayState.m_nSamplesPerTick * ticksPerBeat; // Samps/beat = samps/tick * ticks/beat
|
||||||
} //beats/min = beats/sec * 60
|
bpm = m_MixerSettings.gdwMixingFreq / samplesPerBeat * 60; // Beats/sec = samps/sec / samps/beat
|
||||||
|
} // Beats/min = beats/sec * 60
|
||||||
|
|
||||||
return bpm;
|
return bpm;
|
||||||
}
|
}
|
||||||
|
@ -1043,7 +1045,7 @@ void CSoundFile::ResetChannels()
|
||||||
chn.nLength = 0;
|
chn.nLength = 0;
|
||||||
if(chn.dwFlags[CHN_ADLIB] && m_opl)
|
if(chn.dwFlags[CHN_ADLIB] && m_opl)
|
||||||
{
|
{
|
||||||
CHANNELINDEX c = static_cast<CHANNELINDEX>(std::distance(std::begin(m_PlayState.Chn), &chn));
|
CHANNELINDEX c = static_cast<CHANNELINDEX>(std::distance(m_PlayState.Chn.data(), &chn));
|
||||||
m_opl->NoteCut(c);
|
m_opl->NoteCut(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -509,7 +509,7 @@ public:
|
||||||
ResamplingMode m_nResampling; // Resampling mode (if overriding the globally set resampling)
|
ResamplingMode m_nResampling; // Resampling mode (if overriding the globally set resampling)
|
||||||
int32 m_nRepeatCount = 0; // -1 means repeat infinitely.
|
int32 m_nRepeatCount = 0; // -1 means repeat infinitely.
|
||||||
ORDERINDEX m_nMaxOrderPosition;
|
ORDERINDEX m_nMaxOrderPosition;
|
||||||
ModChannelSettings ChnSettings[MAX_BASECHANNELS]; // Initial channels settings
|
std::array<ModChannelSettings, MAX_BASECHANNELS> ChnSettings; // Initial channels settings
|
||||||
CPatternContainer Patterns;
|
CPatternContainer Patterns;
|
||||||
ModSequenceSet Order; // Pattern sequences (order lists)
|
ModSequenceSet Order; // Pattern sequences (order lists)
|
||||||
protected:
|
protected:
|
||||||
|
@ -589,8 +589,8 @@ public:
|
||||||
bool m_bPositionChanged = true; // Report to plugins that we jumped around in the module
|
bool m_bPositionChanged = true; // Report to plugins that we jumped around in the module
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CHANNELINDEX ChnMix[MAX_CHANNELS]; // Index of channels in Chn to be actually mixed
|
std::array<CHANNELINDEX, MAX_CHANNELS> ChnMix; // Index of channels in Chn to be actually mixed
|
||||||
ModChannel Chn[MAX_CHANNELS]; // Mixing channels... First m_nChannels channels are master channels (i.e. they are never NNA channels)!
|
std::array<ModChannel, MAX_CHANNELS> Chn; // Mixing channels... First m_nChannels channels are master channels (i.e. they are never NNA channels)!
|
||||||
|
|
||||||
struct MIDIMacroEvaluationResults
|
struct MIDIMacroEvaluationResults
|
||||||
{
|
{
|
||||||
|
|
|
@ -670,7 +670,7 @@ bool CSoundFile::ProcessRow()
|
||||||
|
|
||||||
// Reset channel values
|
// Reset channel values
|
||||||
ModCommand *m = Patterns[m_PlayState.m_nPattern].GetpModCommand(m_PlayState.m_nRow, 0);
|
ModCommand *m = Patterns[m_PlayState.m_nPattern].GetpModCommand(m_PlayState.m_nRow, 0);
|
||||||
for (ModChannel *pChn = m_PlayState.Chn, *pEnd = pChn + m_nChannels; pChn != pEnd; pChn++, m++)
|
for (ModChannel *pChn = m_PlayState.Chn.data(), *pEnd = pChn + m_nChannels; pChn != pEnd; pChn++, m++)
|
||||||
{
|
{
|
||||||
// First, handle some quirks that happen after the last tick of the previous row...
|
// First, handle some quirks that happen after the last tick of the previous row...
|
||||||
if(m_playBehaviour[KST3PortaAfterArpeggio]
|
if(m_playBehaviour[KST3PortaAfterArpeggio]
|
||||||
|
|
|
@ -54,7 +54,7 @@ void XMInstrument::ConvertEnvelopeToXM(const InstrumentEnvelope &mptEnv, uint8le
|
||||||
|
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XMInstrument.
|
// Convert OpenMPT's internal sample representation to an XMInstrument.
|
||||||
uint16 XMInstrument::ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport)
|
XMInstrument::SampleList XMInstrument::ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport)
|
||||||
{
|
{
|
||||||
MemsetZero(*this);
|
MemsetZero(*this);
|
||||||
|
|
||||||
|
@ -74,53 +74,49 @@ uint16 XMInstrument::ConvertToXM(const ModInstrument &mptIns, bool compatibility
|
||||||
pitchWheelRange = std::min(mptIns.midiPWD, int8(36));
|
pitchWheelRange = std::min(mptIns.midiPWD, int8(36));
|
||||||
|
|
||||||
// Create sample assignment table
|
// Create sample assignment table
|
||||||
auto sampleList = GetSampleList(mptIns, compatibilityExport);
|
const auto sampleList = GetSampleList(mptIns, compatibilityExport);
|
||||||
for(std::size_t i = 0; i < std::size(sampleMap); i++)
|
for(std::size_t i = 0; i < std::size(sampleMap); i++)
|
||||||
{
|
{
|
||||||
if(mptIns.Keyboard[i + 12] > 0)
|
if(mptIns.Keyboard[i + 12] > 0)
|
||||||
{
|
{
|
||||||
auto sample = std::find(sampleList.begin(), sampleList.end(), mptIns.Keyboard[i + 12]);
|
auto sample = std::find(sampleList.samples.begin(), sampleList.samples.end(), mptIns.Keyboard[i + 12]);
|
||||||
if(sample != sampleList.end())
|
if(sample != sampleList.samples.end())
|
||||||
{
|
{
|
||||||
// Yep, we want to export this sample.
|
// Yep, we want to export this sample.
|
||||||
sampleMap[i] = static_cast<uint8>(sample - sampleList.begin());
|
sampleMap[i] = static_cast<uint8>(std::distance(sampleList.samples.begin(), sample));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<uint16>(sampleList.size());
|
return sampleList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get a list of samples that should be written to the file.
|
// Get a list of samples that should be written to the file.
|
||||||
std::vector<SAMPLEINDEX> XMInstrument::GetSampleList(const ModInstrument &mptIns, bool compatibilityExport) const
|
XMInstrument::SampleList XMInstrument::GetSampleList(const ModInstrument &mptIns, bool compatibilityExport) const
|
||||||
{
|
{
|
||||||
std::vector<SAMPLEINDEX> sampleList; // List of samples associated with this instrument
|
SampleList sampleList; // List of samples associated with this instrument
|
||||||
std::vector<bool> addedToList; // Which samples did we already add to the sample list?
|
std::vector<bool> addedToList; // Which samples did we already add to the sample list?
|
||||||
|
|
||||||
uint8 numSamples = 0;
|
|
||||||
for(std::size_t i = 0; i < std::size(sampleMap); i++)
|
for(std::size_t i = 0; i < std::size(sampleMap); i++)
|
||||||
{
|
{
|
||||||
const SAMPLEINDEX smp = mptIns.Keyboard[i + 12];
|
const SAMPLEINDEX smp = mptIns.Keyboard[i + 12];
|
||||||
if(smp > 0)
|
if(smp == 0)
|
||||||
{
|
continue;
|
||||||
if(smp > addedToList.size())
|
if(smp > addedToList.size())
|
||||||
{
|
addedToList.resize(smp, false);
|
||||||
addedToList.resize(smp, false);
|
if(addedToList[smp - 1])
|
||||||
}
|
continue;
|
||||||
|
// We haven't considered this sample yet.
|
||||||
if(!addedToList[smp - 1] && numSamples < (compatibilityExport ? 16 : 32))
|
addedToList[smp - 1] = true;
|
||||||
{
|
if(sampleList.samples.size() < (compatibilityExport ? 16u : 32u))
|
||||||
// We haven't considered this sample yet.
|
sampleList.samples.push_back(smp);
|
||||||
addedToList[smp - 1] = true;
|
else
|
||||||
numSamples++;
|
sampleList.tooManySamples = true;
|
||||||
sampleList.push_back(smp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// FT2 completely ignores MIDI settings (and also the less important stuff) if not at least one (empty) sample is assigned to this instrument!
|
// FT2 completely ignores MIDI settings (and also the less important stuff) if not at least one (empty) sample is assigned to this instrument!
|
||||||
if(sampleList.empty() && compatibilityExport && midiEnabled)
|
if(sampleList.samples.empty() && compatibilityExport && midiEnabled)
|
||||||
sampleList.assign(1, 0);
|
sampleList.samples.assign(1, 0);
|
||||||
return sampleList;
|
return sampleList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,12 +243,14 @@ void XMInstrumentHeader::Finalise()
|
||||||
|
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XMInstrumentHeader.
|
// Convert OpenMPT's internal sample representation to an XMInstrumentHeader.
|
||||||
void XMInstrumentHeader::ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport)
|
XMInstrument::SampleList XMInstrumentHeader::ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport)
|
||||||
{
|
{
|
||||||
numSamples = instrument.ConvertToXM(mptIns, compatibilityExport);
|
const auto sampleList = instrument.ConvertToXM(mptIns, compatibilityExport);
|
||||||
|
numSamples = static_cast<uint16>(sampleList.samples.size());
|
||||||
mpt::String::WriteBuf(mpt::String::spacePadded, name) = mptIns.name;
|
mpt::String::WriteBuf(mpt::String::spacePadded, name) = mptIns.name;
|
||||||
|
|
||||||
type = mptIns.nMidiProgram; // If FT2 writes crap here, we can do so, too! (we probably shouldn't, though. This is just for backwards compatibility with old MPT versions.)
|
type = mptIns.nMidiProgram; // If FT2 writes crap here, we can do so, too! (we probably shouldn't, though. This is just for backwards compatibility with old MPT versions.)
|
||||||
|
return sampleList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -284,9 +282,10 @@ void XMInstrumentHeader::ConvertToMPT(ModInstrument &mptIns) const
|
||||||
|
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XIInstrumentHeader.
|
// Convert OpenMPT's internal sample representation to an XIInstrumentHeader.
|
||||||
void XIInstrumentHeader::ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport)
|
XMInstrument::SampleList XIInstrumentHeader::ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport)
|
||||||
{
|
{
|
||||||
numSamples = instrument.ConvertToXM(mptIns, compatibilityExport);
|
const auto sampleList = instrument.ConvertToXM(mptIns, compatibilityExport);
|
||||||
|
numSamples = static_cast<uint16>(sampleList.samples.size());
|
||||||
|
|
||||||
memcpy(signature, "Extended Instrument: ", 21);
|
memcpy(signature, "Extended Instrument: ", 21);
|
||||||
mpt::String::WriteBuf(mpt::String::spacePadded, name) = mptIns.name;
|
mpt::String::WriteBuf(mpt::String::spacePadded, name) = mptIns.name;
|
||||||
|
@ -296,6 +295,7 @@ void XIInstrumentHeader::ConvertToXM(const ModInstrument &mptIns, bool compatibi
|
||||||
mpt::String::WriteBuf(mpt::String::spacePadded, trackerName) = openMptTrackerName;
|
mpt::String::WriteBuf(mpt::String::spacePadded, trackerName) = openMptTrackerName;
|
||||||
|
|
||||||
version = 0x102;
|
version = 0x102;
|
||||||
|
return sampleList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct XMFileHeader
|
||||||
};
|
};
|
||||||
|
|
||||||
char signature[17]; // "Extended Module: "
|
char signature[17]; // "Extended Module: "
|
||||||
char songName[20]; // Song Name, not null-terminated (any nulls are treated as spaces)
|
char songName[20]; // Song Name, space-padded
|
||||||
uint8le eof; // DOS EOF Character (0x1A)
|
uint8le eof; // DOS EOF Character (0x1A)
|
||||||
char trackerName[20]; // Software that was used to create the XM file
|
char trackerName[20]; // Software that was used to create the XM file
|
||||||
uint16le version; // File version (1.02 - 1.04 are supported)
|
uint16le version; // File version (1.02 - 1.04 are supported)
|
||||||
|
@ -92,8 +92,14 @@ struct XMInstrument
|
||||||
// Convert XM envelope data to an OpenMPT's internal envelope representation.
|
// Convert XM envelope data to an OpenMPT's internal envelope representation.
|
||||||
void ConvertEnvelopeToMPT(InstrumentEnvelope &mptEnv, uint8 numPoints, uint8 flags, uint8 sustain, uint8 loopStart, uint8 loopEnd, EnvType env) const;
|
void ConvertEnvelopeToMPT(InstrumentEnvelope &mptEnv, uint8 numPoints, uint8 flags, uint8 sustain, uint8 loopStart, uint8 loopEnd, EnvType env) const;
|
||||||
|
|
||||||
|
struct SampleList
|
||||||
|
{
|
||||||
|
std::vector<SAMPLEINDEX> samples; // The list of samples to write to the file
|
||||||
|
bool tooManySamples = false; // Does the source instrument contain more samples than what we can write?
|
||||||
|
};
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XMInstrument.
|
// Convert OpenMPT's internal sample representation to an XMInstrument.
|
||||||
uint16 ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport);
|
SampleList ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport);
|
||||||
// Convert an XMInstrument to OpenMPT's internal instrument representation.
|
// Convert an XMInstrument to OpenMPT's internal instrument representation.
|
||||||
void ConvertToMPT(ModInstrument &mptIns) const;
|
void ConvertToMPT(ModInstrument &mptIns) const;
|
||||||
// Apply auto-vibrato settings from sample to file.
|
// Apply auto-vibrato settings from sample to file.
|
||||||
|
@ -102,7 +108,7 @@ struct XMInstrument
|
||||||
void ApplyAutoVibratoToMPT(ModSample &mptSmp) const;
|
void ApplyAutoVibratoToMPT(ModSample &mptSmp) const;
|
||||||
|
|
||||||
// Get a list of samples that should be written to the file.
|
// Get a list of samples that should be written to the file.
|
||||||
std::vector<SAMPLEINDEX> GetSampleList(const ModInstrument &mptIns, bool compatibilityExport) const;
|
SampleList GetSampleList(const ModInstrument &mptIns, bool compatibilityExport) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
MPT_BINARY_STRUCT(XMInstrument, 230)
|
MPT_BINARY_STRUCT(XMInstrument, 230)
|
||||||
|
@ -112,8 +118,8 @@ MPT_BINARY_STRUCT(XMInstrument, 230)
|
||||||
struct XMInstrumentHeader
|
struct XMInstrumentHeader
|
||||||
{
|
{
|
||||||
uint32le size; // Size of XMInstrumentHeader + XMInstrument
|
uint32le size; // Size of XMInstrumentHeader + XMInstrument
|
||||||
char name[22]; // Instrument Name, not null-terminated (any nulls are treated as spaces)
|
char name[22]; // Instrument Name, space-padded
|
||||||
uint8le type; // Instrument Type (Apparently FT2 writes some crap here, but it's the same crap for all instruments of the same module!)
|
uint8le type; // Instrument Type (FT2 does not initialize this field properly, so it contains a random value, but it's the same random value for all instruments of the same module!)
|
||||||
uint16le numSamples; // Number of Samples associated with instrument
|
uint16le numSamples; // Number of Samples associated with instrument
|
||||||
uint32le sampleHeaderSize; // Size of XMSample
|
uint32le sampleHeaderSize; // Size of XMSample
|
||||||
XMInstrument instrument;
|
XMInstrument instrument;
|
||||||
|
@ -122,7 +128,7 @@ struct XMInstrumentHeader
|
||||||
void Finalise();
|
void Finalise();
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XMInstrument.
|
// Convert OpenMPT's internal sample representation to an XMInstrument.
|
||||||
void ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport);
|
XMInstrument::SampleList ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport);
|
||||||
// Convert an XMInstrument to OpenMPT's internal instrument representation.
|
// Convert an XMInstrument to OpenMPT's internal instrument representation.
|
||||||
void ConvertToMPT(ModInstrument &mptIns) const;
|
void ConvertToMPT(ModInstrument &mptIns) const;
|
||||||
};
|
};
|
||||||
|
@ -139,7 +145,7 @@ struct XIInstrumentHeader
|
||||||
};
|
};
|
||||||
|
|
||||||
char signature[21]; // "Extended Instrument: "
|
char signature[21]; // "Extended Instrument: "
|
||||||
char name[22]; // Instrument Name, not null-terminated (any nulls are treated as spaces)
|
char name[22]; // Instrument Name, space-padded
|
||||||
uint8le eof; // DOS EOF Character (0x1A)
|
uint8le eof; // DOS EOF Character (0x1A)
|
||||||
char trackerName[20]; // Software that was used to create the XI file
|
char trackerName[20]; // Software that was used to create the XI file
|
||||||
uint16le version; // File Version (1.02)
|
uint16le version; // File Version (1.02)
|
||||||
|
@ -147,7 +153,7 @@ struct XIInstrumentHeader
|
||||||
uint16le numSamples; // Number of embedded sample headers + samples
|
uint16le numSamples; // Number of embedded sample headers + samples
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XIInstrumentHeader.
|
// Convert OpenMPT's internal sample representation to an XIInstrumentHeader.
|
||||||
void ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport);
|
XMInstrument::SampleList ConvertToXM(const ModInstrument &mptIns, bool compatibilityExport);
|
||||||
// Convert an XIInstrumentHeader to OpenMPT's internal instrument representation.
|
// Convert an XIInstrumentHeader to OpenMPT's internal instrument representation.
|
||||||
void ConvertToMPT(ModInstrument &mptIns) const;
|
void ConvertToMPT(ModInstrument &mptIns) const;
|
||||||
};
|
};
|
||||||
|
@ -176,7 +182,7 @@ struct XMSample
|
||||||
uint8le pan; // Sample Panning
|
uint8le pan; // Sample Panning
|
||||||
int8le relnote; // Sample Transpose
|
int8le relnote; // Sample Transpose
|
||||||
uint8le reserved; // Reserved (abused for ModPlug's ADPCM compression)
|
uint8le reserved; // Reserved (abused for ModPlug's ADPCM compression)
|
||||||
char name[22]; // Sample Name, not null-terminated (any nulls are treated as spaces)
|
char name[22]; // Sample Name, space-padded
|
||||||
|
|
||||||
// Convert OpenMPT's internal sample representation to an XMSample.
|
// Convert OpenMPT's internal sample representation to an XMSample.
|
||||||
void ConvertToXM(const ModSample &mptSmp, MODTYPE fromType, bool compatibilityExport);
|
void ConvertToXM(const ModSample &mptSmp, MODTYPE fromType, bool compatibilityExport);
|
||||||
|
|
|
@ -177,8 +177,7 @@ static void XFadeSampleImpl(const T *srcIn, const T *srcOut, T *output, const Sm
|
||||||
bool XFadeSample(ModSample &smp, SmpLength fadeLength, int fadeLaw, bool afterloopFade, bool useSustainLoop, CSoundFile &sndFile)
|
bool XFadeSample(ModSample &smp, SmpLength fadeLength, int fadeLaw, bool afterloopFade, bool useSustainLoop, CSoundFile &sndFile)
|
||||||
{
|
{
|
||||||
if(!smp.HasSampleData()) return false;
|
if(!smp.HasSampleData()) return false;
|
||||||
const SmpLength loopStart = useSustainLoop ? smp.nSustainStart : smp.nLoopStart;
|
const auto [loopStart, loopEnd] = useSustainLoop ? smp.GetSustainLoop() : smp.GetLoop();
|
||||||
const SmpLength loopEnd = useSustainLoop ? smp.nSustainEnd : smp.nLoopEnd;
|
|
||||||
|
|
||||||
if(loopEnd <= loopStart || loopEnd > smp.nLength) return false;
|
if(loopEnd <= loopStart || loopEnd > smp.nLength) return false;
|
||||||
if(loopStart < fadeLength) return false;
|
if(loopStart < fadeLength) return false;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2004-2024, OpenMPT Project Developers and Contributors
|
Copyright (c) 2004-2025, OpenMPT Project Developers and Contributors
|
||||||
Copyright (c) 1997-2003, Olivier Lapicque
|
Copyright (c) 1997-2003, Olivier Lapicque
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
#include "mpt/base/detect.hpp"
|
#include "mpt/base/detect.hpp"
|
||||||
#include "mpt/base/namespace.hpp"
|
#include "mpt/base/namespace.hpp"
|
||||||
|
|
||||||
#include "mpt/base/saturate_cast.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace mpt {
|
namespace mpt {
|
||||||
inline namespace MPT_INLINE_NS {
|
inline namespace MPT_INLINE_NS {
|
||||||
|
|
|
@ -93,6 +93,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#elif defined(__CYGWIN__)
|
||||||
|
#define MPT_OS_CYGWIN 1
|
||||||
|
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#define MPT_OS_WINDOWS 1
|
#define MPT_OS_WINDOWS 1
|
||||||
#if !defined(_WIN32_WINDOWS) && !defined(WINVER)
|
#if !defined(_WIN32_WINDOWS) && !defined(WINVER)
|
||||||
|
@ -379,6 +383,9 @@ static_assert(NTDDI_WIN11_GE == MPT_WIN_11_23H2);
|
||||||
#ifndef MPT_OS_EMSCRIPTEN
|
#ifndef MPT_OS_EMSCRIPTEN
|
||||||
#define MPT_OS_EMSCRIPTEN 0
|
#define MPT_OS_EMSCRIPTEN 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MPT_OS_CYGWIN
|
||||||
|
#define MPT_OS_CYGWIN 0
|
||||||
|
#endif
|
||||||
#ifndef MPT_OS_WINDOWS
|
#ifndef MPT_OS_WINDOWS
|
||||||
#define MPT_OS_WINDOWS 0
|
#define MPT_OS_WINDOWS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -241,6 +241,16 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if MPT_OS_CYGWIN
|
||||||
|
#define MPT_LIBCXX_QUIRK_BROKEN_USER_LOCALE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// #define MPT_LIBCXX_QUIRK_BROKEN_ACTIVE_LOCALE
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if MPT_CXX_AT_LEAST(20)
|
#if MPT_CXX_AT_LEAST(20)
|
||||||
// Clang 14 is incompatible with libstdc++ 13 in C++20 mode
|
// Clang 14 is incompatible with libstdc++ 13 in C++20 mode
|
||||||
#if MPT_CLANG_BEFORE(15, 0, 0) && MPT_LIBCXX_GNU_AT_LEAST(13)
|
#if MPT_CLANG_BEFORE(15, 0, 0) && MPT_LIBCXX_GNU_AT_LEAST(13)
|
||||||
|
@ -291,12 +301,16 @@
|
||||||
#elif MPT_OS_MACOSX_OR_IOS
|
#elif MPT_OS_MACOSX_OR_IOS
|
||||||
#if defined(TARGET_OS_OSX)
|
#if defined(TARGET_OS_OSX)
|
||||||
#if TARGET_OS_OSX
|
#if TARGET_OS_OSX
|
||||||
|
#if !defined(MAC_OS_X_VERSION_10_15)
|
||||||
|
#define MPT_LIBCXX_QUIRK_NO_TO_CHARS_INT
|
||||||
|
#else
|
||||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_15)
|
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_15)
|
||||||
#define MPT_LIBCXX_QUIRK_NO_TO_CHARS_INT
|
#define MPT_LIBCXX_QUIRK_NO_TO_CHARS_INT
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,4 +332,20 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if MPT_OS_MACOSX_OR_IOS
|
||||||
|
#if defined(TARGET_OS_OSX)
|
||||||
|
#if TARGET_OS_OSX
|
||||||
|
#if !defined(MAC_OS_X_VERSION_10_14)
|
||||||
|
#define MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE
|
||||||
|
#else
|
||||||
|
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_14)
|
||||||
|
#define MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // MPT_BASE_DETECT_QUIRKS_HPP
|
#endif // MPT_BASE_DETECT_QUIRKS_HPP
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include "mpt/base/math.hpp"
|
#include "mpt/base/math.hpp"
|
||||||
#include "mpt/base/saturate_cast.hpp"
|
#include "mpt/base/saturate_cast.hpp"
|
||||||
|
|
||||||
#include <type_traits>
|
#include <limits>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,11 @@ using std::source_location;
|
||||||
#define MPT_SOURCE_LOCATION_LINE __builtin_LINE()
|
#define MPT_SOURCE_LOCATION_LINE __builtin_LINE()
|
||||||
#define MPT_SOURCE_LOCATION_COLUMN 0
|
#define MPT_SOURCE_LOCATION_COLUMN 0
|
||||||
|
|
||||||
#elif MPT_COMPILER_CLANG && MPT_CLANG_AT_LEAST(9, 0, 0)
|
#elif MPT_COMPILER_CLANG && ((!MPT_OS_MACOSX_OR_IOS && MPT_CLANG_AT_LEAST(9, 0, 0)) || (MPT_OS_MACOSX_OR_IOS && MPT_CLANG_AT_LEAST(12, 0, 0)))
|
||||||
|
|
||||||
|
// We do not know which Apple Clang version introduced __builtin_FILE().
|
||||||
|
// It fails with 10.x (see <https://github.com/fink/fink-distributions/issues/1202>),
|
||||||
|
// and IRC dicussion decided on 12.x as a somewhat safe choice.
|
||||||
|
|
||||||
#define MPT_SOURCE_LOCATION_FILE __builtin_FILE()
|
#define MPT_SOURCE_LOCATION_FILE __builtin_FILE()
|
||||||
#define MPT_SOURCE_LOCATION_FUNCTION __builtin_FUNCTION()
|
#define MPT_SOURCE_LOCATION_FUNCTION __builtin_FUNCTION()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define MPT_CHECK_LIBC_HPP
|
#define MPT_CHECK_LIBC_HPP
|
||||||
|
|
||||||
#include "mpt/base/detect_libc.hpp"
|
#include "mpt/base/detect_libc.hpp"
|
||||||
|
#include "mpt/base/detect_os.hpp"
|
||||||
#include "mpt/base/detect_quirks.hpp"
|
#include "mpt/base/detect_quirks.hpp"
|
||||||
#include "mpt/base/compiletime_warning.hpp"
|
#include "mpt/base/compiletime_warning.hpp"
|
||||||
|
|
||||||
|
@ -30,4 +31,14 @@ MPT_WARNING("C stdlib is not multi-threaded.")
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MPT_CHECK_LIBC_IGNORE_WARNING_UNICODE_MISMATCH
|
||||||
|
#if MPT_OS_WINDOWS
|
||||||
|
#ifdef UNICODE
|
||||||
|
#ifndef _UNICODE
|
||||||
|
MPT_WARNING("UNICODE is defined but _UNICODE is not defined. Please #define _UNICODE.")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif // MPT_OS_WINDOWS
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // MPT_CHECK_LIBC_HPP
|
#endif // MPT_CHECK_LIBC_HPP
|
||||||
|
|
|
@ -20,6 +20,14 @@ MPT_WARNING("Targeting Win9x but windows.h uses UNICODE TCHAR. Please do not #de
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MPT_CHECK_WINDOWS_IGNORE_WARNING_UNICODE_MISMATCH
|
||||||
|
#ifdef _UNICODE
|
||||||
|
#ifndef UNICODE
|
||||||
|
MPT_WARNING("_UNICODE is defined but UNICODE is not defined. Please enable UNICODE support in your compiler, or do not #define _UNICODE.")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NOMINMAX
|
#ifndef NOMINMAX
|
||||||
#ifndef MPT_CHECK_WINDOWS_IGNORE_WARNING_NO_NOMINMAX
|
#ifndef MPT_CHECK_WINDOWS_IGNORE_WARNING_NO_NOMINMAX
|
||||||
MPT_WARNING("windows.h defines min and max which conflicts with C++. Please #define NOMINMAX.")
|
MPT_WARNING("windows.h defines min and max which conflicts with C++. Please #define NOMINMAX.")
|
||||||
|
|
|
@ -135,7 +135,11 @@ public:
|
||||||
m_Filename = tempName;
|
m_Filename = tempName;
|
||||||
m_IsTempFile = true;
|
m_IsTempFile = true;
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_NO_OPTIONAL_VALUE)
|
||||||
|
m_Filename = *(file.GetOptionalFileName());
|
||||||
|
#else
|
||||||
m_Filename = file.GetOptionalFileName().value();
|
m_Filename = file.GetOptionalFileName().value();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} catch (const std::runtime_error &) {
|
} catch (const std::runtime_error &) {
|
||||||
m_Filename = mpt::os_path{};
|
m_Filename = mpt::os_path{};
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "mpt/base/namespace.hpp"
|
#include "mpt/base/namespace.hpp"
|
||||||
#include "mpt/base/saturate_cast.hpp"
|
#include "mpt/base/saturate_cast.hpp"
|
||||||
#include "mpt/detect/mfc.hpp"
|
#include "mpt/detect/mfc.hpp"
|
||||||
|
#include "mpt/out_of_memory/out_of_memory.hpp"
|
||||||
#include "mpt/string/types.hpp"
|
#include "mpt/string/types.hpp"
|
||||||
#include "mpt/string/utility.hpp"
|
#include "mpt/string/utility.hpp"
|
||||||
|
|
||||||
|
@ -1664,10 +1665,60 @@ inline Tdststring encode(logical_encoding encoding, const mpt::widestring & src)
|
||||||
#elif !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
#elif !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
||||||
switch (encoding) {
|
switch (encoding) {
|
||||||
case logical_encoding::locale:
|
case logical_encoding::locale:
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_BROKEN_USER_LOCALE)
|
||||||
|
try {
|
||||||
|
return encode_locale<Tdststring>(std::locale(""), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return encode_locale<Tdststring>(std::locale(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return encode_locale<Tdststring>(std::locale::classic(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
return encode_ascii<Tdststring>(src);
|
||||||
|
#else
|
||||||
return encode_locale<Tdststring>(std::locale(""), src);
|
return encode_locale<Tdststring>(std::locale(""), src);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case logical_encoding::active_locale:
|
case logical_encoding::active_locale:
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_BROKEN_ACTIVE_LOCALE)
|
||||||
|
try {
|
||||||
|
return encode_locale<Tdststring>(std::locale(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return encode_locale<Tdststring>(std::locale(""), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return encode_locale<Tdststring>(std::locale::classic(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
return encode_ascii<Tdststring>(src);
|
||||||
|
#else
|
||||||
return encode_locale<Tdststring>(std::locale(), src);
|
return encode_locale<Tdststring>(std::locale(), src);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw std::domain_error("unsupported encoding");
|
throw std::domain_error("unsupported encoding");
|
||||||
|
@ -1835,10 +1886,60 @@ inline mpt::widestring decode(logical_encoding encoding, const Tsrcstring & src)
|
||||||
#elif !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
#elif !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
|
||||||
switch (encoding) {
|
switch (encoding) {
|
||||||
case logical_encoding::locale:
|
case logical_encoding::locale:
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_BROKEN_USER_LOCALE)
|
||||||
|
try {
|
||||||
|
return decode_locale(std::locale(""), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return decode_locale(std::locale(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return decode_locale(std::locale::classic(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
return decode_ascii(src);
|
||||||
|
#else
|
||||||
return decode_locale(std::locale(""), src);
|
return decode_locale(std::locale(""), src);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
case logical_encoding::active_locale:
|
case logical_encoding::active_locale:
|
||||||
|
#if defined(MPT_LIBCXX_QUIRK_BROKEN_USER_LOCALE)
|
||||||
|
try {
|
||||||
|
return decode_locale(std::locale(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return decode_locale(std::locale(""), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return decode_locale(std::locale::classic(), src);
|
||||||
|
} catch (mpt::out_of_memory e) {
|
||||||
|
mpt::rethrow_out_of_memory(e);
|
||||||
|
} catch (...) {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
return decode_ascii(src);
|
||||||
|
#else
|
||||||
return decode_locale(std::locale(), src);
|
return decode_locale(std::locale(), src);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw std::domain_error("unsupported encoding");
|
throw std::domain_error("unsupported encoding");
|
||||||
|
|
Loading…
Reference in a new issue