Skip to content

Commit

Permalink
Merged revision(s) 20780 from branches/OpenMPT-1.31:
Browse files Browse the repository at this point in the history
Merged revision(s) 20736 from trunk/OpenMPT:
[Imp] STK: Allow romantic.stk to load, which has a sample longer than 74KB.
[Imp] STK: Also allow files to load that have garbage in the song title, but whose sample names are properly null-terminated non-empty ASCII strings. Fixes STK.Sharks-NewIntro.
........

........


git-svn-id: https://source.openmpt.org/svn/openmpt/branches/OpenMPT-1.30@20781 56274372-70c3-4bfc-bfc3-4c3a0b034d27
  • Loading branch information
sagamusix committed May 11, 2024
1 parent d1f3096 commit 9bf983f
Showing 1 changed file with 38 additions and 6 deletions.
44 changes: 38 additions & 6 deletions soundlib/Load_mod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1355,6 +1355,34 @@ static uint32 CountInvalidChars(const char (&name)[N])
}


enum class NameClassification
{
Empty,
ValidASCII,
Invalid,
};

// Check if a name is a valid null-terminated ASCII string with no garbage after the null terminator, or if it's empty
static NameClassification ClassifyName(const mpt::span<const char> name) noexcept
{
bool foundNull = false, foundNormal = false;
for(auto c : name)
{
if(c > 0 && c < ' ')
return NameClassification::Invalid;
if(c == 0)
foundNull = true;
else if(foundNull)
return NameClassification::Invalid;
else
foundNormal = true;
}
if(!foundNull)
return NameClassification::Invalid;
return foundNormal ? NameClassification::ValidASCII : NameClassification::Empty;
}


// We'll have to do some heuristic checks to find out whether this is an old Ultimate Soundtracker module
// or if it was made with the newer Soundtracker versions.
// Thanks for Fraggie for this information! (https://www.un4seen.com/forum/?topic=14471.msg100829#msg100829)
Expand Down Expand Up @@ -1393,7 +1421,8 @@ static bool ValidateHeader(const M15FileHeaders &fileHeaders)

SmpLength totalSampleLen = 0;
uint8 allVolumes = 0;
uint8 diskNameCount = 0;
uint8 validNameCount = 0;
bool invalidNames = false;

for(SAMPLEINDEX smp = 0; smp < 15; smp++)
{
Expand All @@ -1404,13 +1433,16 @@ 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++;
if(const auto nameType = ClassifyName(sampleHeader.name); nameType == NameClassification::ValidASCII)
validNameCount++;
else if(nameType == NameClassification::Invalid)
invalidNames = true;

// Sanity checks - invalid character count adjusted for ata.mod (MD5 937b79b54026fa73a1a4d3597c26eace, SHA1 3322ca62258adb9e0ae8e9afe6e0c29d39add874)
// Sample length adjusted for romantic.stk which has a (valid) sample of length 72222
if(invalidChars > 48
|| sampleHeader.volume > 64
|| sampleHeader.length > 32768)
|| sampleHeader.length > 37000)
{
return false;
}
Expand All @@ -1419,8 +1451,8 @@ 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)
// scramble_2.mod has a lot of garbage in the song title, but it has lots of properly-formatted sample names, so we consider those to be more important than the garbage bytes.
if(invalidCharsInTitle > 5 && (validNameCount < 4 || invalidNames))
{
return false;
}
Expand Down

0 comments on commit 9bf983f

Please sign in to comment.