From: <sv...@op...> - 2024-04-02 21:18:51
|
Author: sagamusix Date: Tue Apr 2 23:18:43 2024 New Revision: 20487 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20487 Log: Merged revision(s) 20101, 20486 from trunk/OpenMPT: [Mod] MOD: Change VBlank timing heuristic to always assume CIA timing when long samples (= unsupported by original ProTracker) are found. ........ [Fix] MOD: Avoid NoiseTracker detection if emnpty sample slots have a default volume other than 0 (https://bugs.openmpt.org/view.php?id=1765). [Fix] MOD: 7-bit panning detection may have returned incorrect results for MODs with a channel count other than 4 (in particular with 1-3 channels, it was possible that sample data could have influenced the heuristic). ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/soundlib/Load_mod.cpp Modified: branches/OpenMPT-1.31/soundlib/Load_mod.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_mod.cpp Tue Apr 2 23:14:08 2024 (r20486) +++ branches/OpenMPT-1.31/soundlib/Load_mod.cpp Tue Apr 2 23:18:43 2024 (r20487) @@ -885,6 +885,7 @@ SmpLength totalSampleLen = 0, wowSampleLen = 0; m_nSamples = 31; uint32 invalidBytes = 0; + bool hasLongSamples = false; for(SAMPLEINDEX smp = 1; smp <= 31; smp++) { MODSampleHeader sampleHeader = ReadAndSwap<MODSampleHeader>(file, modMagicResult.swapBytes); @@ -894,7 +895,7 @@ if(isHMNT) Samples[smp].nFineTune = -static_cast<int8>(sampleHeader.finetune << 3); else if(Samples[smp].nLength > 65535) - isNoiseTracker = false; + hasLongSamples = true; if(sampleHeader.length && !sampleHeader.loopLength) hasRepLen0 = true; @@ -994,7 +995,7 @@ // Before loading patterns, apply some heuristics: // - Scan patterns to check if file could be a NoiseTracker file in disguise. - // In this case, the parameter of Dxx commands needs to be ignored. + // In this case, the parameter of Dxx commands needs to be ignored (see 1.11song2.mod, 2-3song6.mod). // - Use the same code to find notes that would be out-of-range on Amiga. // - Detect 7-bit panning and whether 8xx / E8x commands should be interpreted as panning at all. bool onlyAmigaNotes = true; @@ -1003,13 +1004,13 @@ const uint8 ENABLE_MOD_PANNING_THRESHOLD = 0x30; if(!isNoiseTracker) { + const uint32 patternLength = m_nChannels * 64; bool leftPanning = false, extendedPanning = false; // For detecting 800-880 panning - isNoiseTracker = isMdKd; + isNoiseTracker = isMdKd && !hasEmptySampleWithVolume && !hasLongSamples; for(PATTERNINDEX pat = 0; pat < numPatterns; pat++) { uint16 patternBreaks = 0; - - for(uint32 i = 0; i < 256; i++) + for(uint32 i = 0; i < patternLength; i++) { ModCommand m; const auto data = ReadAndSwap<std::array<uint8, 4>>(file, modMagicResult.swapBytes && pat == 0); @@ -1044,9 +1045,10 @@ } file.Seek(modMagicResult.patternDataOffset); - const CHANNELINDEX readChannels = (isFLT8 ? 4 : m_nChannels); // 4 channels per pattern in FLT8 format. - if(isFLT8) numPatterns++; // as one logical pattern consists of two real patterns in FLT8 format, the highest pattern number has to be increased by one. - bool hasTempoCommands = false, definitelyCIA = false; // for detecting VBlank MODs + const CHANNELINDEX readChannels = (isFLT8 ? 4 : m_nChannels); // 4 channels per pattern in FLT8 format. + if(isFLT8) + numPatterns++; // as one logical pattern consists of two real patterns in FLT8 format, the highest pattern number has to be increased by one. + bool hasTempoCommands = false, definitelyCIA = hasLongSamples; // for detecting VBlank MODs // Heuristic for rejecting E0x commands that are most likely not intended to actually toggle the Amiga LED filter, like in naen_leijasi_ptk.mod by ilmarque bool filterState = false; int filterTransitions = 0; @@ -1245,6 +1247,8 @@ file.Seek(nextSample); } } + if(isMdKd && file.ReadArray<char, 9>() == std::array<char, 9>{0x00, 0x11, 0x55, 0x33, 0x22, 0x11, 0x04, 0x01, 0x01}) + modMagicResult.madeWithTracker = UL_("Tetramed"); } #if defined(MPT_EXTERNAL_SAMPLES) || defined(MPT_BUILD_FUZZER) @@ -1361,8 +1365,7 @@ // Check if a name string is valid (i.e. doesn't contain binary garbage data) -template <size_t N> -static uint32 CountInvalidChars(const char (&name)[N]) +static uint32 CountInvalidChars(const mpt::span<const char> name) { uint32 invalidChars = 0; for(int8 c : name) // char can be signed or unsigned |