diff --git a/soundlib/ITTools.cpp b/soundlib/ITTools.cpp index 98bd1a6382..0200cbf083 100644 --- a/soundlib/ITTools.cpp +++ b/soundlib/ITTools.cpp @@ -530,10 +530,9 @@ void ITSample::ConvertToIT(const ModSample &mptSmp, MODTYPE fromType, bool compr // Convert an ITSample to OpenMPT's internal sample representation. uint32 ITSample::ConvertToMPT(ModSample &mptSmp) const { - if(memcmp(id, "IMPS", 4)) - { - return 0; - } + // IT does not check for the IMPS magic, and some bad XM->IT converter out there doesn't write the magic bytes for empty sample slots. + //if(memcmp(id, "IMPS", 4)) + // return 0; mptSmp.Initialize(MOD_TYPE_IT); mptSmp.SetDefaultCuePoints(); // For old IT/MPTM files diff --git a/soundlib/Load_it.cpp b/soundlib/Load_it.cpp index a8654c3921..102665637d 100644 --- a/soundlib/Load_it.cpp +++ b/soundlib/Load_it.cpp @@ -784,6 +784,19 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) bool possibleXMconversion = false; + // There's a bug in IT somewhere that resets the "sample data present" flag in sample headers, but keeps the sample length + // of a previously deleted sample (presumably). + // As old ModPlug versions didn't set this flag under some circumstances (if a sample wasn't referenced by any instruments in instrument mode), + // and because there appear to be some external tools that forget to set this flag at all, we only respect the flag if the file + // vaguely looks like it was saved with IT. Some files that play garbage data if we don't do this: + // astral projection.it by Lord Jon Ray + // classic illusions.it by Blackstar + // deep in dance.it by Simply DJ + // There are many more such files but they don't reference the broken samples in their pattern data, or the sample data pointer + // points right to the end of the file, so in both cases no audible problem can be observed. + const bool muteBuggySamples = !interpretModPlugMade && fileHeader.cwtv >= 0x0100 && fileHeader.cwtv <= 0x0217 + && (fileHeader.cwtv < 0x0207 || fileHeader.reserved != 0); + // Reading Samples m_nSamples = std::min(static_cast(fileHeader.smpnum), static_cast(MAX_SAMPLES - 1)); bool lastSampleCompressed = false, anyADPCM = false; @@ -792,9 +805,10 @@ bool CSoundFile::ReadIT(FileReader &file, ModLoadingFlags loadFlags) ITSample sampleHeader; if(smpPos[i] > 0 && file.Seek(smpPos[i]) && file.ReadStruct(sampleHeader)) { - // IT does not check for the IMPS magic, and some bad XM->IT converter out there doesn't write the magic bytes for empty sample slots. ModSample &sample = Samples[i + 1]; size_t sampleOffset = sampleHeader.ConvertToMPT(sample); + if(muteBuggySamples && !(sampleHeader.flags & ITSample::sampleDataPresent)) + sample.nLength = 0; m_szNames[i + 1] = mpt::String::ReadBuf(mpt::String::spacePadded, sampleHeader.name);