Skip to content

Commit

Permalink
[Mod] M15: The heuristics in r20524 were a bit too loose, also identi…
Browse files Browse the repository at this point in the history
…fying some GMC files as SoundTracker modules. Tighten the song title check again to previous values, but ignore it if a sufficent amount of sample headers has "real-looking" sample names (starting with a disk name like st-01:...).

git-svn-id: https://source.openmpt.org/svn/openmpt/trunk/OpenMPT@20538 56274372-70c3-4bfc-bfc3-4c3a0b034d27
  • Loading branch information
sagamusix committed Apr 8, 2024
1 parent 9b8cc06 commit 7f1874b
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions soundlib/Load_mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,11 @@ struct MODSampleHeader
+ ((loopStart > length * 2) ? 1 : 0);
}

bool HasDiskName() const
{
return (!memcmp(name, "st-", 3) || !memcmp(name, "ST-", 3)) && name[5] == ':';
}

// Suggested threshold for rejecting invalid files based on cumulated score returned by GetInvalidByteScore
static constexpr uint32 INVALID_BYTE_THRESHOLD = 40;

Expand Down Expand Up @@ -1410,15 +1415,13 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)
// However, there are quite a few SoundTracker modules in the wild with random
// characters. To still be able to distguish them from other formats, we just reject
// files with *too* many bogus characters. Arbitrary threshold: 48 bogus characters in total
// or more than 11 invalid characters just in the title alone (just enough to make scramble_2.mod load).
uint32 invalidChars = CountInvalidChars(fileHeaders.songname);
if(invalidChars > 11)
{
return false;
}
// or more than 5 invalid characters just in the title alone
uint32 invalidCharsInTitle = CountInvalidChars(fileHeaders.songname);
uint32 invalidChars = invalidCharsInTitle;

SmpLength totalSampleLen = 0;
uint8 allVolumes = 0;
uint8 diskNameCount = 0;

for(SAMPLEINDEX smp = 0; smp < 15; smp++)
{
Expand All @@ -1429,6 +1432,8 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)
// schmokk.mod has a non-zero value here but it should not be treated as finetune
if(sampleHeader.finetune != 0)
invalidChars += 16;
if(sampleHeader.HasDiskName())
diskNameCount++;

// Sanity checks - invalid character count adjusted for ata.mod (MD5 937b79b54026fa73a1a4d3597c26eace, SHA1 3322ca62258adb9e0ae8e9afe6e0c29d39add874)
if(invalidChars > 48
Expand All @@ -1442,6 +1447,12 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)
allVolumes |= sampleHeader.volume;
}

// scramble_2.mod has a lot of garbage in the song title, but it has lots of sample names starting with st-01, so we consider those to be more important than the garbage bytes.
if(invalidCharsInTitle > 5 && diskNameCount < 4)
{
return false;
}

// Reject any files with no (or only silent) samples at all, as this might just be a random binary file (e.g. ID3 tags with tons of padding)
if(totalSampleLen == 0 || allVolumes == 0)
{
Expand Down Expand Up @@ -1548,7 +1559,7 @@ bool CSoundFile::ReadM15(FileReader &file, ModLoadingFlags loadFlags)

totalSampleLen += mptSmp.nLength;

if(m_szNames[smp][0] && ((memcmp(m_szNames[smp].buf, "st-", 3) && memcmp(m_szNames[smp].buf, "ST-", 3)) || m_szNames[smp][5] != ':'))
if(m_szNames[smp][0] && sampleHeader.HasDiskName())
{
// Ultimate Soundtracker 1.8 and D.O.C. SoundTracker IX always have sample names containing disk names.
hasDiskNames = false;
Expand Down

0 comments on commit 7f1874b

Please sign in to comment.