Index: build/android_ndk/Android.mk =================================================================== --- build/android_ndk/Android.mk (revision 7555) +++ build/android_ndk/Android.mk (working copy) @@ -187,6 +187,7 @@ soundlib/Load_s3m.cpp \ soundlib/Load_sfx.cpp \ soundlib/Load_stm.cpp \ + soundlib/Load_stp.cpp \ soundlib/Load_ult.cpp \ soundlib/Load_umx.cpp \ soundlib/Load_wav.cpp \ Index: build/autotools/Makefile.am =================================================================== --- build/autotools/Makefile.am (revision 7555) +++ build/autotools/Makefile.am (working copy) @@ -205,6 +205,7 @@ libopenmpt_la_SOURCES += soundlib/Load_s3m.cpp libopenmpt_la_SOURCES += soundlib/Load_sfx.cpp libopenmpt_la_SOURCES += soundlib/Load_stm.cpp +libopenmpt_la_SOURCES += soundlib/Load_stp.cpp libopenmpt_la_SOURCES += soundlib/Load_ult.cpp libopenmpt_la_SOURCES += soundlib/Load_umx.cpp libopenmpt_la_SOURCES += soundlib/Load_wav.cpp @@ -463,6 +464,7 @@ libopenmpttest_SOURCES += soundlib/Load_s3m.cpp libopenmpttest_SOURCES += soundlib/Load_sfx.cpp libopenmpttest_SOURCES += soundlib/Load_stm.cpp +libopenmpttest_SOURCES += soundlib/Load_stp.cpp libopenmpttest_SOURCES += soundlib/Load_ult.cpp libopenmpttest_SOURCES += soundlib/Load_umx.cpp libopenmpttest_SOURCES += soundlib/Load_wav.cpp Index: build/vs2010/libopenmpt-small.vcxproj =================================================================== --- build/vs2010/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2010/libopenmpt-small.vcxproj (working copy) @@ -529,6 +529,7 @@ + Index: build/vs2010/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2010/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2010/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2010/libopenmpt.vcxproj =================================================================== --- build/vs2010/libopenmpt.vcxproj (revision 7555) +++ build/vs2010/libopenmpt.vcxproj (working copy) @@ -529,6 +529,7 @@ + Index: build/vs2010/libopenmpt.vcxproj.filters =================================================================== --- build/vs2010/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2010/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2010/libopenmpt_test.vcxproj =================================================================== --- build/vs2010/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2010/libopenmpt_test.vcxproj (working copy) @@ -361,6 +361,7 @@ + Index: build/vs2010/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2010/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2010/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2010xp/libopenmpt-small.vcxproj =================================================================== --- build/vs2010xp/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2010xp/libopenmpt-small.vcxproj (working copy) @@ -527,6 +527,7 @@ + Index: build/vs2010xp/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2010xp/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2010xp/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2010xp/libopenmpt.vcxproj =================================================================== --- build/vs2010xp/libopenmpt.vcxproj (revision 7555) +++ build/vs2010xp/libopenmpt.vcxproj (working copy) @@ -527,6 +527,7 @@ + Index: build/vs2010xp/libopenmpt.vcxproj.filters =================================================================== --- build/vs2010xp/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2010xp/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2010xp/libopenmpt_test.vcxproj =================================================================== --- build/vs2010xp/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2010xp/libopenmpt_test.vcxproj (working copy) @@ -360,6 +360,7 @@ + Index: build/vs2010xp/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2010xp/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2010xp/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2012/libopenmpt-small.vcxproj =================================================================== --- build/vs2012/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2012/libopenmpt-small.vcxproj (working copy) @@ -537,6 +537,7 @@ + Index: build/vs2012/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2012/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2012/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2012/libopenmpt.vcxproj =================================================================== --- build/vs2012/libopenmpt.vcxproj (revision 7555) +++ build/vs2012/libopenmpt.vcxproj (working copy) @@ -537,6 +537,7 @@ + Index: build/vs2012/libopenmpt.vcxproj.filters =================================================================== --- build/vs2012/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2012/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2012/libopenmpt_test.vcxproj =================================================================== --- build/vs2012/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2012/libopenmpt_test.vcxproj (working copy) @@ -365,6 +365,7 @@ + Index: build/vs2012/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2012/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2012/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2012xp/libopenmpt-small.vcxproj =================================================================== --- build/vs2012xp/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2012xp/libopenmpt-small.vcxproj (working copy) @@ -537,6 +537,7 @@ + Index: build/vs2012xp/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2012xp/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2012xp/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2012xp/libopenmpt.vcxproj =================================================================== --- build/vs2012xp/libopenmpt.vcxproj (revision 7555) +++ build/vs2012xp/libopenmpt.vcxproj (working copy) @@ -537,6 +537,7 @@ + Index: build/vs2012xp/libopenmpt.vcxproj.filters =================================================================== --- build/vs2012xp/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2012xp/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2012xp/libopenmpt_test.vcxproj =================================================================== --- build/vs2012xp/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2012xp/libopenmpt_test.vcxproj (working copy) @@ -365,6 +365,7 @@ + Index: build/vs2012xp/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2012xp/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2012xp/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013/libopenmpt-small.vcxproj =================================================================== --- build/vs2013/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2013/libopenmpt-small.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2013/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2013/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2013/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013/libopenmpt.vcxproj =================================================================== --- build/vs2013/libopenmpt.vcxproj (revision 7555) +++ build/vs2013/libopenmpt.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2013/libopenmpt.vcxproj.filters =================================================================== --- build/vs2013/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2013/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013/libopenmpt_test.vcxproj =================================================================== --- build/vs2013/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2013/libopenmpt_test.vcxproj (working copy) @@ -366,6 +366,7 @@ + Index: build/vs2013/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2013/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2013/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013/OpenMPT.vcxproj =================================================================== --- build/vs2013/OpenMPT.vcxproj (revision 7555) +++ build/vs2013/OpenMPT.vcxproj (working copy) @@ -1062,6 +1062,7 @@ + Index: build/vs2013/OpenMPT.vcxproj.filters =================================================================== --- build/vs2013/OpenMPT.vcxproj.filters (revision 7555) +++ build/vs2013/OpenMPT.vcxproj.filters (working copy) @@ -1169,6 +1169,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013xp/libopenmpt-small.vcxproj =================================================================== --- build/vs2013xp/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2013xp/libopenmpt-small.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2013xp/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2013xp/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2013xp/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013xp/libopenmpt.vcxproj =================================================================== --- build/vs2013xp/libopenmpt.vcxproj (revision 7555) +++ build/vs2013xp/libopenmpt.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2013xp/libopenmpt.vcxproj.filters =================================================================== --- build/vs2013xp/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2013xp/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013xp/libopenmpt_test.vcxproj =================================================================== --- build/vs2013xp/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2013xp/libopenmpt_test.vcxproj (working copy) @@ -366,6 +366,7 @@ + Index: build/vs2013xp/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2013xp/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2013xp/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2013xp/OpenMPT.vcxproj =================================================================== --- build/vs2013xp/OpenMPT.vcxproj (revision 7555) +++ build/vs2013xp/OpenMPT.vcxproj (working copy) @@ -1062,6 +1062,7 @@ + Index: build/vs2013xp/OpenMPT.vcxproj.filters =================================================================== --- build/vs2013xp/OpenMPT.vcxproj.filters (revision 7555) +++ build/vs2013xp/OpenMPT.vcxproj.filters (working copy) @@ -1169,6 +1169,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015/libopenmpt-small.vcxproj =================================================================== --- build/vs2015/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2015/libopenmpt-small.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2015/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2015/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2015/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015/libopenmpt.vcxproj =================================================================== --- build/vs2015/libopenmpt.vcxproj (revision 7555) +++ build/vs2015/libopenmpt.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2015/libopenmpt.vcxproj.filters =================================================================== --- build/vs2015/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2015/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015/libopenmpt_test.vcxproj =================================================================== --- build/vs2015/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2015/libopenmpt_test.vcxproj (working copy) @@ -366,6 +366,7 @@ + Index: build/vs2015/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2015/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2015/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015/OpenMPT.vcxproj =================================================================== --- build/vs2015/OpenMPT.vcxproj (revision 7555) +++ build/vs2015/OpenMPT.vcxproj (working copy) @@ -1062,6 +1062,7 @@ + Index: build/vs2015/OpenMPT.vcxproj.filters =================================================================== --- build/vs2015/OpenMPT.vcxproj.filters (revision 7555) +++ build/vs2015/OpenMPT.vcxproj.filters (working copy) @@ -1178,6 +1178,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015xp/libopenmpt-small.vcxproj =================================================================== --- build/vs2015xp/libopenmpt-small.vcxproj (revision 7555) +++ build/vs2015xp/libopenmpt-small.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2015xp/libopenmpt-small.vcxproj.filters =================================================================== --- build/vs2015xp/libopenmpt-small.vcxproj.filters (revision 7555) +++ build/vs2015xp/libopenmpt-small.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015xp/libopenmpt.vcxproj =================================================================== --- build/vs2015xp/libopenmpt.vcxproj (revision 7555) +++ build/vs2015xp/libopenmpt.vcxproj (working copy) @@ -538,6 +538,7 @@ + Index: build/vs2015xp/libopenmpt.vcxproj.filters =================================================================== --- build/vs2015xp/libopenmpt.vcxproj.filters (revision 7555) +++ build/vs2015xp/libopenmpt.vcxproj.filters (working copy) @@ -515,6 +515,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015xp/libopenmpt_test.vcxproj =================================================================== --- build/vs2015xp/libopenmpt_test.vcxproj (revision 7555) +++ build/vs2015xp/libopenmpt_test.vcxproj (working copy) @@ -366,6 +366,7 @@ + Index: build/vs2015xp/libopenmpt_test.vcxproj.filters =================================================================== --- build/vs2015xp/libopenmpt_test.vcxproj.filters (revision 7555) +++ build/vs2015xp/libopenmpt_test.vcxproj.filters (working copy) @@ -533,6 +533,9 @@ soundlib + + soundlib + soundlib Index: build/vs2015xp/OpenMPT.vcxproj =================================================================== --- build/vs2015xp/OpenMPT.vcxproj (revision 7555) +++ build/vs2015xp/OpenMPT.vcxproj (working copy) @@ -1062,6 +1062,7 @@ + Index: build/vs2015xp/OpenMPT.vcxproj.filters =================================================================== --- build/vs2015xp/OpenMPT.vcxproj.filters (revision 7555) +++ build/vs2015xp/OpenMPT.vcxproj.filters (working copy) @@ -1178,6 +1178,9 @@ soundlib + + soundlib + soundlib Index: installer/filetypes.iss =================================================================== --- installer/filetypes.iss (revision 7555) +++ installer/filetypes.iss (working copy) @@ -47,6 +47,7 @@ Name: "associate_exotic\sfx2"; Description: "SoundFX 2 (SFX2)"; Name: "associate_exotic\st26"; Description: "SoundTracker 2.6 (ST26)"; Name: "associate_exotic\stm"; Description: "Scream Tracker 2 (STM)"; +Name: "associate_exotic\stp"; Description: "Soundtracker Pro II (STP)"; Name: "associate_exotic\ult"; Description: "UltraTracker (ULT)"; Name: "associate_exotic\umx"; Description: "Unreal Music (UMX)"; Name: "associate_exotic\wow"; Description: "Grave Composer (WOW)"; @@ -95,6 +96,7 @@ Root: HKCR; Subkey: ".sfx2"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\sfx2 Root: HKCR; Subkey: ".st26"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\st26 Root: HKCR; Subkey: ".stm"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\stm +Root: HKCR; Subkey: ".stp"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\stp Root: HKCR; Subkey: ".ult"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\ult Root: HKCR; Subkey: ".umx"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\umx Root: HKCR; Subkey: ".wow"; ValueType: string; ValueName: ""; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: associate_exotic\wow @@ -165,6 +167,7 @@ Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".sfx2"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".st26"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".stm"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable +Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".stp"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".ult"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".umx"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Clients\Media\OpenMPT\Capabilities\FileAssociations"; ValueType: string; ValueName: ".wow"; ValueData: "OpenMPTFile"; Flags: uninsdeletevalue; Tasks: not portable @@ -211,6 +214,7 @@ Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".sfx2"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".st26"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".stm"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable +Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".stp"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".ult"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".umx"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable Root: HKLM; Subkey: "Software\Classes\Applications\mptrack.exe\SupportedTypes"; ValueType: string; ValueName: ".wow"; ValueData: ""; Flags: uninsdeletevalue; Tasks: not portable Index: libopenmpt/foo_openmpt.cpp =================================================================== --- libopenmpt/foo_openmpt.cpp (revision 7555) +++ libopenmpt/foo_openmpt.cpp (working copy) @@ -319,6 +319,7 @@ "*.imf" ";" "*.j2b" ";" "*.plm" ";" + "*.stp" ";" "*.sfx" ";" "*.sfx2" ";" "*.mms" ";" Index: mptrack/Mptrack.cpp =================================================================== --- mptrack/Mptrack.cpp (revision 7555) +++ mptrack/Mptrack.cpp (working copy) @@ -1431,7 +1431,7 @@ "FastTracker Modules (*.xm)|*.xm;*.xmz|" "Impulse Tracker Modules (*.it)|*.it;*.itz|" "OpenMPT Modules (*.mptm)|*.mptm;*.mptmz|" - "Other Modules (mtm,okt,mdl,669,far,...)|*.mtm;*.669;*.ult;*.wow;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.med;*.ams;*.dbm;*.digi;*.dsm;*.umx;*.amf;*.psm;*.mt2;*.gdm;*.imf;*.itp;*.j2b;*.ice;*.st26;*.plm;*.sfx;*.sfx2;*.mms|" + "Other Modules (mtm,okt,mdl,669,far,...)|*.mtm;*.669;*.ult;*.wow;*.far;*.mdl;*.okt;*.dmf;*.ptm;*.med;*.ams;*.dbm;*.digi;*.dsm;*.umx;*.amf;*.psm;*.mt2;*.gdm;*.imf;*.itp;*.j2b;*.ice;*.st26;*.plm;*.stp;*.sfx;*.sfx2;*.mms|" "Wave Files (*.wav)|*.wav|" "MIDI Files (*.mid,*.rmi)|*.mid;*.rmi;*.smf|" "All Files (*.*)|*.*||") Index: soundlib/Load_stp.cpp =================================================================== --- soundlib/Load_stp.cpp (nonexistent) +++ soundlib/Load_stp.cpp (working copy) @@ -0,0 +1,923 @@ +/* + * Load_stp.cpp + * ------------ + * Purpose: STP (Soundtracker Pro II) module loader + * Notes : A few exotic effects aren't supported. + * Multiple sample loops are supported, but only the first 10 can be used as cue points + * (with 16xx and 18xx). + * Fractional speed values and combined auto effects are handled whenever possible, + * but some effects may be omitted (and there may be tempo accuracy issues). + * Authors: Devin Acker + * OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + * + * Wisdom from the Soundtracker Pro II manual: + * "To create shorter patterns, simply create shorter patterns." + */ + +#include "stdafx.h" +#include "Loaders.h" + +OPENMPT_NAMESPACE_BEGIN + +// File header (except for "STP3" magic) +struct STPFileHeader +{ + uint16be version; + uint8be numOrders; + uint8be patternLength; + uint8be orderList[128]; + uint16be speed; + uint16be speedFrac; + uint16be timerCount; + uint16be flags; + uint32be reserved; + uint16be midiCount; // always 50 + uint8be midi[50]; + uint16be numSamples; + uint16be sampleStructSize; +}; + +MPT_BINARY_STRUCT(STPFileHeader, 200); + + +// Sample header (versions 0 and 1) +struct STPSampleHeaderOld +{ + char pathName[31]; + uint8be flags; + char fileName[30]; + uint32be length; + uint8be volume; + uint8be reserved1; + uint32be loopStart; + uint32be loopLength; + uint16be defaultCmd; + uint32be reserved2; + + void ConvertToMPT(ModSample &mptSmp) const + { + mptSmp.Initialize(MOD_TYPE_MOD); + mptSmp.nLength = length; + mptSmp.nVolume = 4u * std::min(volume, 64); + + mptSmp.nLoopStart = loopStart; + mptSmp.nLoopEnd = loopStart + loopLength; + + if(mptSmp.nLoopStart >= mptSmp.nLength) + { + mptSmp.nLoopStart = mptSmp.nLength - 1; + } + if(mptSmp.nLoopEnd > mptSmp.nLength) + { + mptSmp.nLoopEnd = mptSmp.nLength; + } + + if(mptSmp.nLoopStart > mptSmp.nLoopEnd) + { + mptSmp.nLoopStart = 0; + mptSmp.nLoopEnd = 0; + } + else if(mptSmp.nLoopEnd > mptSmp.nLoopStart) + { + mptSmp.uFlags.set(CHN_LOOP); + } + } + + void Read(FileReader &file) + { + file.ReadStruct(*this); + } +}; + +MPT_BINARY_STRUCT(STPSampleHeaderOld, 82); + + +// Sample header (version 2), no endian-defined integers due to variable string length and alignment in file (we read the fields manually) +struct STPSampleHeader +{ + //char pathName[256]; + uint8 flags; + char fileName[30]; + uint32 length; + uint8 volume; + uint8 reserved1; + uint32 loopStart; + uint32 loopLength; + uint16 defaultCmd; + uint16 defaultPeriod; + uint8 finetune; + uint8 reserved2; + + void ConvertToMPT(ModSample &mptSmp) const + { + mptSmp.Initialize(MOD_TYPE_MOD); + mptSmp.nLength = length; + mptSmp.nFineTune = static_cast(finetune << 3); + mptSmp.nVolume = 4 * std::min(volume, 64); + + mptSmp.nLoopStart = loopStart; + mptSmp.nLoopEnd = loopStart + loopLength; + + if(mptSmp.nLoopStart >= mptSmp.nLength) + { + mptSmp.nLoopStart = mptSmp.nLength - 1; + } + if(mptSmp.nLoopEnd > mptSmp.nLength) + { + mptSmp.nLoopEnd = mptSmp.nLength; + } + + if(mptSmp.nLoopStart > mptSmp.nLoopEnd) + { + mptSmp.nLoopStart = 0; + mptSmp.nLoopEnd = 0; + } else if(mptSmp.nLoopEnd > mptSmp.nLoopStart) + { + mptSmp.cues[0] = mptSmp.nLoopStart; + mptSmp.uFlags.set(CHN_LOOP); + } + } + + void Read(FileReader &file) + { + std::string str; + + file.ReadNullString(str, 255); + //mpt::String::Copy(pathName, str); + + flags = file.ReadUint8(); + + file.ReadNullString(str, 29); + mpt::String::Copy(fileName, str); + + // seek to even boundary + if(file.GetPosition() % 2u) + file.Skip(1); + + length = file.ReadUint32BE(); + volume = file.ReadUint8(); + reserved1 = file.ReadUint8(); + + loopStart = file.ReadUint32BE(); + loopLength = file.ReadUint32BE(); + + defaultCmd = file.ReadUint16BE(); + defaultPeriod = file.ReadUint16BE(); + + finetune = file.ReadUint8(); + reserved2 = file.ReadUint8(); + } +}; + +struct STPLoopInfo +{ + SmpLength loopStart; + SmpLength loopLength; + SAMPLEINDEX looped; + SAMPLEINDEX nonLooped; +}; + +typedef std::vector STPLoopList; + +template +static void ReadSample(FileReader &file, T &sampleHeader, ModSample &sample, char (&sampleName)[MAX_SAMPLENAME]) +//-------------------------------------------------------------------------------------------------------------- +{ + sampleHeader.Read(file); + sampleHeader.ConvertToMPT(sample); + + mpt::String::Read(sampleName, sampleHeader.fileName); +} + + +static TEMPO ConvertTempo(uint16 ciaSpeed) +//---------------------------------------- +{ + // 3546 is the resulting CIA timer value when using 4F7D (tempo 125 bpm) command in STProII + return TEMPO((125.0 * 3546.0) / ciaSpeed); +} + + +static void ConvertLoopSlice(ModSample &src, ModSample &dest, SmpLength start, SmpLength len, bool loop) +//------------------------------------------------------------------------------------------------------ +{ + if(!src.HasSampleData()) return; + + dest.FreeSample(); + + dest = src; + dest.nLength = len; + dest.pSample = nullptr; + + if(!dest.AllocateSample()) + { + return; + } + + // only preserve cue points if the target sample length is the same + if(len != src.nLength) + MemsetZero(dest.cues); + + std::memcpy(dest.pSample8, src.pSample8 + start, len); + if(loop) + { + dest.nLoopStart = 0; + dest.nLoopEnd = len; + dest.uFlags.set(CHN_LOOP); + } else + { + dest.nLoopStart = 0; + dest.nLoopEnd = 0; + dest.uFlags.reset(CHN_LOOP); + } +} + +static void ConvertLoopSequence(ModSample &smp, STPLoopList &loopList) +//-------------------------------------------------------------------- +{ + // This should only modify a sample if it has more than one loop + // (otherwise, it behaves like a normal sample loop) + if(!smp.HasSampleData() || loopList.size() < 2) return; + + ModSample newSmp = smp; + newSmp.nLength = 0; + newSmp.pSample = nullptr; + + size_t numLoops = loopList.size(); + + // get the total length of the sample after combining all looped sections + for(size_t i = 0; i < numLoops; i++) + { + STPLoopInfo &info = loopList[i]; + + // if adding this loop would cause the sample length to exceed maximum, + // then limit and bail out + if((newSmp.nLength + info.loopLength > MAX_SAMPLE_LENGTH) || + (info.loopLength > MAX_SAMPLE_LENGTH) || + (info.loopStart + info.loopLength > smp.nLength)) + { + numLoops = i; + break; + } + + newSmp.nLength += info.loopLength; + } + + if(!newSmp.AllocateSample()) + { + return; + } + + // start copying the looped sample data parts + SmpLength start = 0; + + for(size_t i = 0; i < numLoops; i++) + { + STPLoopInfo &info = loopList[i]; + + memcpy(newSmp.pSample8 + start, smp.pSample8 + info.loopStart, info.loopLength); + + // update loop info based on position in edited sample + info.loopStart = start; + if(i > 0 && i <= CountOf(newSmp.cues)) + { + newSmp.cues[i - 1] = start; + } + start += info.loopLength; + } + + // replace old sample with new one + smp.FreeSample(); + smp = newSmp; + + smp.nLoopStart = 0; + smp.nLoopEnd = smp.nLength; + smp.uFlags.set(CHN_LOOP); +} + + +bool CSoundFile::ReadSTP(FileReader &file, ModLoadingFlags loadFlags) +//------------------------------------------------------------------- +{ + file.Rewind(); + if(!file.ReadMagic("STP3")) + return false; + + STPFileHeader fileHeader; + file.ReadStruct(fileHeader); + if(fileHeader.version > 2 + || fileHeader.numOrders > 128 + || fileHeader.numSamples >= MAX_SAMPLES + || fileHeader.midiCount != 50) + return false; + + if(loadFlags == onlyVerifyHeader) + return true; + + InitializeGlobals(MOD_TYPE_STP); + + m_nChannels = 4; + m_nSamples = 0; + m_nInstruments = 0; + + m_nDefaultSpeed = fileHeader.speed; + m_nDefaultTempo = ConvertTempo(fileHeader.timerCount); + + m_nMinPeriod = 14 * 4; + m_nMaxPeriod = 3424 * 4; + + Order.ReadFromArray(fileHeader.orderList, fileHeader.numOrders); + + std::vector loopInfo; + // non-looped versions of samples with loops (when needed) + std::vector nonLooped; + + // Load sample headers + SAMPLEINDEX samplesInFile = 0; + + for(SAMPLEINDEX smp = 1; smp <= fileHeader.numSamples; smp++) + { + // this is 1-based the same as smp + SAMPLEINDEX actualSmp = file.ReadUint16BE(); + if(actualSmp >= MAX_SAMPLES) + return false; + + samplesInFile = m_nSamples = std::max(m_nSamples, actualSmp); + + ModSample &thisSmp = Samples[actualSmp]; + + if(fileHeader.version == 2) + { + STPSampleHeader sampleHeader; + uint32 headerSize = file.ReadUint32BE(); + + ReadSample(file, sampleHeader, thisSmp, m_szNames[actualSmp]); + // TODO: verify string lengths against headerSize? + MPT_UNUSED_VARIABLE(headerSize); + } else + { + STPSampleHeaderOld sampleHeaderOld; + ReadSample(file, sampleHeaderOld, thisSmp, m_szNames[actualSmp]); + } + + STPLoopList loopList; + + if(fileHeader.version >= 1) + { + uint16 numLoops = file.ReadUint16BE(); + + STPLoopInfo loop; + loop.looped = loop.nonLooped = 0; + + if(numLoops == 0 && thisSmp.uFlags[CHN_LOOP]) + { + loop.loopStart = thisSmp.nLoopStart; + loop.loopLength = thisSmp.nLoopEnd - thisSmp.nLoopStart; + loopList.push_back(loop); + } else for(SAMPLEINDEX i = 0; i < numLoops; i++) + { + loop.loopStart = file.ReadUint32BE(); + loop.loopLength = file.ReadUint32BE(); + loopList.push_back(loop); + } + } + + if(actualSmp) + { + nonLooped.resize(actualSmp); + loopInfo.resize(actualSmp); + loopInfo[actualSmp - 1] = loopList; + } + } + + // Load patterns + uint16 numPatterns = 128; + if(fileHeader.version == 0) + numPatterns = file.ReadUint16BE(); + + uint16 patternLength = fileHeader.patternLength; + CHANNELINDEX channels = 4; + if(fileHeader.version > 0) + { + // Scan for total number of channels + FileReader::off_t patOffset = file.GetPosition(); + for(uint16 pat = 0; pat < numPatterns; pat++) + { + PATTERNINDEX actualPat = file.ReadUint16BE(); + if(actualPat == 0xFFFF) + break; + + patternLength = file.ReadUint16BE(); + channels = file.ReadUint16BE(); + m_nChannels = std::max(m_nChannels, channels); + + file.Skip(channels * patternLength * 4u); + } + file.Seek(patOffset); + if(m_nChannels > MAX_BASECHANNELS) + return false; + } + + uint8 globalVolSlide = 0; + std::vector autoFinePorta(m_nChannels, 0); + std::vector autoPortaUp(m_nChannels, 0); + std::vector autoPortaDown(m_nChannels, 0); + std::vector autoVolSlide(m_nChannels, 0); + std::vector autoVibrato(m_nChannels, 0); + std::vector vibratoMem(m_nChannels, 0); + std::vector autoTremolo(m_nChannels, 0); + std::vector autoTonePorta(m_nChannels, 0); + std::vector tonePortaMem(m_nChannels, 0); + + for(uint16 pat = 0; pat < numPatterns; pat++) + { + PATTERNINDEX actualPat = pat; + + if(fileHeader.version > 0) + { + actualPat = file.ReadUint16BE(); + if(actualPat == 0xFFFF) + break; + + patternLength = file.ReadUint16BE(); + channels = file.ReadUint16BE(); + } + + if(!(loadFlags & loadPatternData) || !Patterns.Insert(actualPat, patternLength)) + { + file.Skip(channels * patternLength * 4u); + continue; + } + + for(ROWINDEX row = 0; row < patternLength; row++) + { + PatternRow rowBase = Patterns[actualPat].GetpModCommand(row, 0); + + bool didGlobalVolSlide = false; + bool shouldDelay = false; + + // if a fractional speed value is in use then determine if we should stick a fine pattern delay somewhere + switch(fileHeader.speedFrac & 3) + { + // 1/4 + case 1: shouldDelay = (row & 3) == 0; break; + // 1/2 + case 2: shouldDelay = (row & 1) == 0; break; + // 3/4 + case 3: shouldDelay = (row & 3) != 3; break; + } + + for(CHANNELINDEX chn = 0; chn < channels; chn++) + { + ModCommand &m = rowBase[chn]; + uint8 data[4]; + file.ReadArray(data); + + m.instr = data[0]; + m.note = data[1]; + m.command = data[2]; + m.param = data[3]; + + if(m.note) + { + m.note += 24 + NOTE_MIN; + + autoFinePorta[chn] = 0; + autoPortaUp[chn] = 0; + autoPortaDown[chn] = 0; + autoVolSlide[chn] = 0; + autoVibrato[chn] = vibratoMem[chn] = 0; + autoTremolo[chn] = 0; + autoTonePorta[chn] = tonePortaMem[chn] = 0; + } + + // this is a nibble-swapped param value used for auto fine volside + // and auto global fine volside + uint8 swap = (m.param >> 4) | (m.param << 4); + + if((m.command & 0xF0) == 0xF0) + { + m.param = mpt::saturate_cast(Util::Round(ConvertTempo(m.param | (((uint16)m.command & 0xF) << 8)).ToDouble())); + m.command = CMD_TEMPO; + } else switch(m.command) + { + case 0x00: // arpeggio + if(m.param) + m.command = CMD_ARPEGGIO; + break; + + case 0x01: // portamento up + m.command = CMD_PORTAMENTOUP; + break; + + case 0x02: // portamento down + m.command = CMD_PORTAMENTODOWN; + break; + + case 0x03: // auto fine portamento up + autoFinePorta[chn] = 0x10 | std::min(m.param, ModCommand::PARAM(15)); + autoPortaUp[chn] = 0; + autoPortaDown[chn] = 0; + autoTonePorta[chn] = 0; + + m.command = m.param = 0; + break; + + case 0x04: // auto fine portamento down + autoFinePorta[chn] = 0x20 | std::min(m.param, ModCommand::PARAM(15)); + autoPortaUp[chn] = 0; + autoPortaDown[chn] = 0; + autoTonePorta[chn] = 0; + + m.command = m.param = 0; + break; + + case 0x05: // auto portamento up + autoFinePorta[chn] = 0; + autoPortaUp[chn] = m.param; + autoPortaDown[chn] = 0; + autoTonePorta[chn] = 0; + + m.command = m.param = 0; + break; + + case 0x06: // auto portamento down + autoFinePorta[chn] = 0; + autoPortaUp[chn] = 0; + autoPortaDown[chn] = m.param; + autoTonePorta[chn] = 0; + + m.command = m.param = 0; + break; + + case 0x07: // set global volume + m.command = CMD_GLOBALVOLUME; + globalVolSlide = 0; + break; + + case 0x08: // auto global fine volume slide + globalVolSlide = swap; + m.command = m.param = 0; + break; + + case 0x09: // fine portamento up + m.command = CMD_MODCMDEX; + m.param = 0x10 | std::min(m.param, ModCommand::PARAM(15)); + break; + + case 0x0A: // fine portamento down + m.command = CMD_MODCMDEX; + m.param = 0x20 | std::min(m.param, ModCommand::PARAM(15)); + break; + + case 0x0B: // auto fine volume slide + autoVolSlide[chn] = swap; + m.command = m.param = 0; + break; + + case 0x0C: // set volume + m.volcmd = VOLCMD_VOLUME; + m.vol = m.param; + autoVolSlide[chn] = 0; + m.command = m.param = 0; + break; + + case 0x0D: // volume slide (param is swapped compared to .mod) + if(m.param & 0xF0) + { + m.volcmd = VOLCMD_VOLSLIDEDOWN; + m.vol = m.param >> 4; + } else if(m.param & 0x0F) + { + m.volcmd = VOLCMD_VOLSLIDEUP; + m.vol = m.param & 0xF; + } + autoVolSlide[chn] = 0; + m.command = m.param = 0; + break; + + case 0x0E: // set filter (also uses opposite value compared to .mod) + m.command = CMD_MODCMDEX; + m.param = 1 ^ (m.param ? 1 : 0); + break; + + case 0x0F: // set speed + m.command = CMD_SPEED; + fileHeader.speedFrac = m.param & 0xF; + m.param >>= 4; + break; + + case 0x10: // auto vibrato + autoVibrato[chn] = m.param; + vibratoMem[chn] = 0; + m.command = m.param = 0; + break; + + case 0x11: // auto tremolo + if(m.param & 0xF) + autoTremolo[chn] = m.param; + else + autoTremolo[chn] = 0; + m.command = m.param = 0; + break; + + case 0x12: // pattern break + m.command = CMD_PATTERNBREAK; + break; + + case 0x13: // auto tone portamento + autoFinePorta[chn] = 0; + autoPortaUp[chn] = 0; + autoPortaDown[chn] = 0; + autoTonePorta[chn] = m.param; + + tonePortaMem[chn] = 0; + m.command = m.param = 0; + break; + + case 0x14: // position jump + m.command = CMD_POSITIONJUMP; + break; + + case 0x16: // start loop sequence + if(m.instr && m.instr <= loopInfo.size()) + { + STPLoopList &loopList = loopInfo[m.instr - 1]; + + m.param--; + if(m.param < std::min(MPT_ARRAY_COUNT(ModSample().cues), loopList.size())) + { + m.volcmd = VOLCMD_OFFSET; + m.vol = m.param; + } + } + + m.command = m.param = 0; + break; + + case 0x17: // play only loop nn + if(m.instr && m.instr <= loopInfo.size()) + { + STPLoopList &loopList = loopInfo[m.instr - 1]; + + m.param--; + if(m.param < loopList.size()) + { + if(!loopList[m.param].looped && m_nSamples < MAX_SAMPLES - 1) + loopList[m.param].looped = ++m_nSamples; + m.instr = static_cast(loopList[m.param].looped); + } + } + + m.command = m.param = 0; + break; + + case 0x18: // play sequence without loop + if(m.instr && m.instr <= loopInfo.size()) + { + STPLoopList &loopList = loopInfo[m.instr - 1]; + + m.param--; + if(m.param < std::min(MPT_ARRAY_COUNT(ModSample().cues), loopList.size())) + { + m.volcmd = VOLCMD_OFFSET; + m.vol = m.param; + } + // switch to non-looped version of sample and create it if needed + if(!nonLooped[m.instr - 1] && m_nSamples < MAX_SAMPLES - 1) + nonLooped[m.instr - 1] = ++m_nSamples; + m.instr = static_cast(nonLooped[m.instr - 1]); + } + + m.command = m.param = 0; + break; + + case 0x19: // play only loop nn without loop + if(m.instr && m.instr <= loopInfo.size()) + { + STPLoopList &loopList = loopInfo[m.instr - 1]; + + m.param--; + if(m.param < loopList.size()) + { + if(!loopList[m.param].nonLooped && m_nSamples < MAX_SAMPLES-1) + loopList[m.param].nonLooped = ++m_nSamples; + m.instr = static_cast(loopList[m.param].nonLooped); + } + } + + m.command = m.param = 0; + break; + + case 0x1D: // fine volume slide (nibble order also swapped) + m.command = CMD_VOLUMESLIDE; + m.param = swap; + if(m.param & 0xF0) // slide down + m.param |= 0x0F; + else if(m.param & 0x0F) + m.param |= 0xF0; + break; + + case 0x20: // "delayed fade" + // just behave like either a normal fade or a notecut + // depending on the speed + if(m.param & 0xF0) + { + autoVolSlide[chn] = m.param >> 4; + m.command = m.param = 0; + } else + { + m.command = CMD_MODCMDEX; + m.param = 0xC0 | (m.param & 0xF); + } + break; + + case 0x21: // note delay + m.command = CMD_MODCMDEX; + m.param = 0xD0 | std::min(m.param, ModCommand::PARAM(15)); + break; + + case 0x22: // retrigger note + m.command = CMD_RETRIG; + m.param = std::min(m.param, ModCommand::PARAM(15)); + break; + + case 0x49: // set sample offset + m.command = CMD_OFFSET; + break; + + case 0x4E: // other protracker commands (pattern loop / delay) + if((m.param & 0xF0) == 0x60 || (m.param & 0xF0) == 0xE0) + m.command = CMD_MODCMDEX; + else + m.command = m.param = 0; + break; + + case 0x4F: // set speed/tempo + if(m.param < 0x20) + { + m.command = CMD_SPEED; + fileHeader.speedFrac = 0; + } else + { + m.command = CMD_TEMPO; + } + break; + + default: + m.command = CMD_NONE; + break; + } + + bool didVolSlide = false; + + // try to put volume slide in volume command + if(autoVolSlide[chn] && !m.volcmd) + { + if(autoVolSlide[chn] & 0xF0) + { + m.volcmd = VOLCMD_FINEVOLUP; + m.vol = autoVolSlide[chn] >> 4; + } else + { + m.volcmd = VOLCMD_FINEVOLDOWN; + m.vol = autoVolSlide[chn] & 0xF; + } + didVolSlide = true; + } + + // try to place/combine all remaining running effects. + if(m.command == CMD_NONE) + { + if(autoPortaUp[chn]) + { + m.command = CMD_PORTAMENTOUP; + m.param = autoPortaUp[chn]; + + } else if(autoPortaDown[chn]) + { + m.command = CMD_PORTAMENTODOWN; + m.param = autoPortaDown[chn]; + + } else if(autoFinePorta[chn]) + { + m.command = CMD_MODCMDEX; + m.param = autoFinePorta[chn]; + + } else if(autoTonePorta[chn]) + { + m.command = CMD_TONEPORTAMENTO; + m.param = tonePortaMem[chn] = autoTonePorta[chn]; + + } else if(autoVibrato[chn]) + { + m.command = CMD_VIBRATO; + m.param = vibratoMem[chn] = autoVibrato[chn]; + + } else if(!didVolSlide && autoVolSlide[chn]) + { + m.command = CMD_VOLUMESLIDE; + m.param = autoVolSlide[chn]; + // convert to a "fine" value by setting the other nibble to 0xF + if(m.param & 0x0F) + m.param |= 0xF0; + else if(m.param & 0xF0) + m.param |= 0x0F; + didVolSlide = true; + + } else if(autoTremolo[chn]) + { + m.command = CMD_TREMOLO; + m.param = autoTremolo[chn]; + + } else if(shouldDelay) + { + // insert a fine pattern delay here + m.command = CMD_S3MCMDEX; + m.param = 0x61; + shouldDelay = false; + + } else if(!didGlobalVolSlide && globalVolSlide) + { + m.command = CMD_GLOBALVOLSLIDE; + m.param = globalVolSlide; + // convert to a "fine" value by setting the other nibble to 0xF + if(m.param & 0x0F) + m.param |= 0xF0; + else if(m.param & 0xF0) + m.param |= 0x0F; + + didGlobalVolSlide = true; + } + } + } + + // TODO: create/use extra channels for global volslide/delay if needed + } + } + + // after we know how many channels there really are... + m_nSamplePreAmp = 256 / m_nChannels; + // Setup channel pan positions and volume + SetupMODPanning(true); + + // Skip over scripts and drumpad info + if(fileHeader.version > 0) + { + while(file.CanRead(2)) + { + uint16 scriptNum = file.ReadUint16BE(); + if(scriptNum == 0xFFFF) + break; + + file.Skip(2); + uint32 length = file.ReadUint32BE(); + file.Skip(length); + } + + // Skip drumpad stuff + file.Skip(17*2); + } + + // Reading samples + if(loadFlags & loadSampleData) + { + for(SAMPLEINDEX smp = 1; smp <= samplesInFile; smp++) if(Samples[smp].nLength) + { + SampleIO( + SampleIO::_8bit, + SampleIO::mono, + SampleIO::littleEndian, + SampleIO::signedPCM) + .ReadSample(Samples[smp], file); + + ConvertLoopSequence(Samples[smp], loopInfo[smp - 1]); + + // make a non-looping duplicate of this sample if needed + if(nonLooped[smp - 1]) + { + ConvertLoopSlice(Samples[smp], Samples[nonLooped[smp-1]], 0, Samples[smp].nLength, false); + } + + for(SAMPLEINDEX loop = 0; loop < loopInfo[smp - 1].size(); loop++) + { + STPLoopInfo &info = loopInfo[smp - 1][loop]; + + // make duplicate samples for this individual section if needed + if(info.looped) + { + ConvertLoopSlice(Samples[smp], Samples[info.looped], info.loopStart, info.loopLength, true); + } + if(info.nonLooped) + { + ConvertLoopSlice(Samples[smp], Samples[info.nonLooped], info.loopStart, info.loopLength, false); + } + } + } + } + + return true; +} + +OPENMPT_NAMESPACE_END Property changes on: soundlib/Load_stp.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/x-c++src \ No newline at end of property Index: soundlib/Snd_defs.h =================================================================== --- soundlib/Snd_defs.h (revision 7555) +++ soundlib/Snd_defs.h (working copy) @@ -98,6 +98,7 @@ MOD_TYPE_UAX = 0x10000000, // sampleset as module MOD_TYPE_PLM = 0x20000000, MOD_TYPE_SFX = 0x40000000, + MOD_TYPE_STP = 0x80000000, }; DECLARE_FLAGSET(MODTYPE) Index: soundlib/Snd_fx.cpp =================================================================== --- soundlib/Snd_fx.cpp (revision 7555) +++ soundlib/Snd_fx.cpp (working copy) @@ -3434,7 +3434,7 @@ else param = pChn->nOldPortaUpDown; - const bool doFineSlides = !doFinePortamentoAsRegular && !(GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_AMF0 | MOD_TYPE_DIGI)); + const bool doFineSlides = !doFinePortamentoAsRegular && !(GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_AMF0 | MOD_TYPE_DIGI | MOD_TYPE_STP)); // Process MIDI pitch bend for instrument plugins MidiPortamento(nChn, param, doFineSlides); @@ -3493,7 +3493,7 @@ else param = pChn->nOldPortaUpDown; - const bool doFineSlides = !doFinePortamentoAsRegular && !(GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_AMF0 | MOD_TYPE_DIGI)); + const bool doFineSlides = !doFinePortamentoAsRegular && !(GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_AMF0 | MOD_TYPE_DIGI | MOD_TYPE_STP)); // Process MIDI pitch bend for instrument plugins MidiPortamento(nChn, -static_cast(param), doFineSlides); @@ -3989,7 +3989,7 @@ else param = pChn->nOldVolumeSlide; - if((GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_DIGI))) + if((GetType() & (MOD_TYPE_MOD | MOD_TYPE_XM | MOD_TYPE_MT2 | MOD_TYPE_MED | MOD_TYPE_DIGI | MOD_TYPE_STP))) { // MOD / XM nibble priority if((param & 0xF0) != 0) Index: soundlib/Sndfile.cpp =================================================================== --- soundlib/Sndfile.cpp (revision 7555) +++ soundlib/Sndfile.cpp (working copy) @@ -309,6 +309,7 @@ && !ReadJ2B(file, loadFlags) && !ReadPT36(file, loadFlags) && !ReadSFX(file, loadFlags) + && !ReadSTP(file, loadFlags) && !ReadMod(file, loadFlags) && !ReadICE(file, loadFlags) && !Read669(file, loadFlags) @@ -1075,6 +1076,7 @@ case MOD_TYPE_AMF0: case MOD_TYPE_DIGI: case MOD_TYPE_SFX: + case MOD_TYPE_STP: return MOD_TYPE_MOD; case MOD_TYPE_MED: if(m_nDefaultTempo == TEMPO(125, 0) && m_nDefaultSpeed == 6 && !m_nInstruments) Index: soundlib/Sndfile.h =================================================================== --- soundlib/Sndfile.h (revision 7555) +++ soundlib/Sndfile.h (working copy) @@ -680,6 +680,7 @@ bool ReadS3M(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); bool ReadSFX(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); bool ReadSTM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); + bool ReadSTP(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); bool ReadUlt(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); bool ReadUMX(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); bool ReadWav(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule); @@ -884,7 +885,7 @@ // Returns true if the current format uses transpose+finetune rather than frequency in Hz to specify middle-C. static bool UseFinetuneAndTranspose(MODTYPE type) { - return (type & (MOD_TYPE_AMF0 | MOD_TYPE_DIGI | MOD_TYPE_MED | MOD_TYPE_MOD | MOD_TYPE_MTM | MOD_TYPE_OKT | MOD_TYPE_SFX | MOD_TYPE_XM)); + return (type & (MOD_TYPE_AMF0 | MOD_TYPE_DIGI | MOD_TYPE_MED | MOD_TYPE_MOD | MOD_TYPE_MTM | MOD_TYPE_OKT | MOD_TYPE_SFX | MOD_TYPE_STP | MOD_TYPE_XM)); } bool UseFinetuneAndTranspose() const { Index: soundlib/Tables.cpp =================================================================== --- soundlib/Tables.cpp (revision 7555) +++ soundlib/Tables.cpp (working copy) @@ -90,6 +90,7 @@ { MOD_TYPE_SFX, "SoundFX", "sfx" }, { MOD_TYPE_SFX, "SoundFX", "sfx2" }, { MOD_TYPE_SFX, "MultiMedia Sound", "mms" }, + { MOD_TYPE_STP, "Soundtracker Pro II", "stp" }, #ifndef NO_ARCHIVE_SUPPORT // Compressed modules @@ -151,6 +152,7 @@ { MOD_TYPE_DBM , mpt::CharsetISO8859_1 }, { MOD_TYPE_DIGI, mpt::CharsetISO8859_1 }, { MOD_TYPE_SFX , mpt::CharsetISO8859_1 }, + { MOD_TYPE_STP, mpt::CharsetISO8859_1 }, // Amiga // DOS { MOD_TYPE_MOD , mpt::CharsetISO8859_1 }, { MOD_TYPE_MED , mpt::CharsetISO8859_1 },