From: <sv...@op...> - 2024-05-08 17:54:01
|
Author: sagamusix Date: Wed May 8 19:53:49 2024 New Revision: 20736 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20736 Log: [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. Modified: trunk/OpenMPT/soundlib/Load_stk.cpp trunk/OpenMPT/soundlib/MODTools.cpp trunk/OpenMPT/soundlib/MODTools.h Modified: trunk/OpenMPT/soundlib/Load_stk.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_stk.cpp Wed May 8 18:52:54 2024 (r20735) +++ trunk/OpenMPT/soundlib/Load_stk.cpp Wed May 8 19:53:49 2024 (r20736) @@ -51,7 +51,8 @@ SmpLength totalSampleLen = 0; uint8 allVolumes = 0; - uint8 diskNameCount = 0; + uint8 validNameCount = 0; + bool invalidNames = false; for(SAMPLEINDEX smp = 0; smp < 15; smp++) { @@ -62,13 +63,16 @@ // 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; } @@ -77,8 +81,8 @@ 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; } Modified: trunk/OpenMPT/soundlib/MODTools.cpp ============================================================================== --- trunk/OpenMPT/soundlib/MODTools.cpp Wed May 8 18:52:54 2024 (r20735) +++ trunk/OpenMPT/soundlib/MODTools.cpp Wed May 8 19:53:49 2024 (r20736) @@ -314,7 +314,7 @@ // Check if a name string is valid (i.e. doesn't contain binary garbage data) -uint32 CountInvalidChars(const mpt::span<const char> name) +uint32 CountInvalidChars(const mpt::span<const char> name) noexcept { uint32 invalidChars = 0; for(int8 c : name) // char can be signed or unsigned @@ -327,6 +327,27 @@ } +// Check if a name is a valid null - terminated ASCII string with no garbage after the null terminator, or if it's empty +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; +} + + // Count malformed bytes in MOD pattern data uint32 CountMalformedMODPatternData(const MODPatternData &patternData, const bool extendedFormat) { Modified: trunk/OpenMPT/soundlib/MODTools.h ============================================================================== --- trunk/OpenMPT/soundlib/MODTools.h Wed May 8 18:52:54 2024 (r20735) +++ trunk/OpenMPT/soundlib/MODTools.h Wed May 8 19:53:49 2024 (r20736) @@ -108,7 +108,18 @@ // Check if a name string is valid (i.e. doesn't contain binary garbage data) -uint32 CountInvalidChars(const mpt::span<const char> name); +uint32 CountInvalidChars(const mpt::span<const char> name) noexcept; + + +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 +NameClassification ClassifyName(const mpt::span<const char> name) noexcept; // Count malformed bytes in MOD pattern data |