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
|