From: <sv...@op...> - 2024-10-27 15:49:40
|
Author: sagamusix Date: Sun Oct 27 16:49:28 2024 New Revision: 22004 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=22004 Log: [Imp] S3M: Fingerprint early Schism Tracker versions, as found in some 2007-ish S3Ms by Platonist. Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp Sun Oct 27 14:15:50 2024 (r22003) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp Sun Oct 27 16:49:28 2024 (r22004) @@ -232,6 +232,15 @@ m_nMinPeriod = 64; m_nMaxPeriod = 32767; + ReadOrderFromFile<uint8>(Order(), file, fileHeader.ordNum, 0xFF, 0xFE); + + // Read sample header offsets + std::vector<uint16le> sampleOffsets; + file.ReadVector(sampleOffsets, fileHeader.smpNum); + // Read pattern offsets + std::vector<uint16le> patternOffsets; + file.ReadVector(patternOffsets, fileHeader.patNum); + // ST3 ignored Zxx commands, so if we find that a file was made with ST3, we should erase all MIDI macros. bool keepMidiMacros = false; @@ -241,6 +250,7 @@ bool isST3 = false; bool isSchism = false; const bool usePanningTable = fileHeader.usePanningTable == S3MFileHeader::idPanning; + const bool offsetsAreCanonical = !patternOffsets.empty() && !sampleOffsets.empty() && patternOffsets[0] > sampleOffsets[0]; const int32 schismDateVersion = SchismTrackerEpoch + ((fileHeader.cwtv == 0x4FFF) ? fileHeader.reserved2 : (fileHeader.cwtv - 0x4050)); switch(fileHeader.cwtv & S3MFileHeader::trackerMask) { @@ -252,18 +262,25 @@ if(!memcmp(&fileHeader.reserved2, "SCLUB2.0", 8)) { madeWithTracker = UL_("Sound Club 2"); - } else if(fileHeader.cwtv == S3MFileHeader::trkST3_20 && fileHeader.special == 0 && (fileHeader.ordNum & 0x0F) == 0 && fileHeader.ultraClicks == 0 && (fileHeader.flags & ~0x50) == 0 && usePanningTable) + } else if(fileHeader.cwtv == S3MFileHeader::trkST3_20 && fileHeader.special == 0 && (fileHeader.ordNum & 0x01) == 0 && fileHeader.ultraClicks == 0 && (fileHeader.flags & ~0x50) == 0 && usePanningTable && offsetsAreCanonical) { - // MPT and OpenMPT before 1.17.03.02 - Simply keep default (filter) MIDI macros - if((fileHeader.masterVolume & 0x80) != 0) + // Canonical offset check avoids mis-detection of an automatic conversion of Vic's "Paper" demo track + if((fileHeader.ordNum & 0x0F) == 0) { - m_dwLastSavedWithVersion = MPT_V("1.16"); - madeWithTracker = UL_("ModPlug Tracker / OpenMPT 1.17"); - } else + // MPT and OpenMPT before 1.17.03.02 - Simply keep default (filter) MIDI macros + if((fileHeader.masterVolume & 0x80) != 0) + { + m_dwLastSavedWithVersion = MPT_V("1.16"); + madeWithTracker = UL_("ModPlug Tracker / OpenMPT 1.17"); + } else + { + // MPT 1.0 alpha5 doesn't set the stereo flag, but MPT 1.0 alpha6 does. + m_dwLastSavedWithVersion = MPT_V("1.00.00.A0"); + madeWithTracker = UL_("ModPlug Tracker 1.0 alpha"); + } + } else if((fileHeader.masterVolume & 0x80) != 0) { - // MPT 1.0 alpha5 doesn't set the stereo flag, but MPT 1.0 alpha6 does. - m_dwLastSavedWithVersion = MPT_V("1.00.00.A0"); - madeWithTracker = UL_("ModPlug Tracker 1.0 alpha"); + madeWithTracker = UL_("Schism Tracker"); } keepMidiMacros = true; nonCompatTracker = true; @@ -308,7 +325,7 @@ madeWithTracker = UL_("Impulse Tracker 1.03"); // Could also be 1.02, maybe? I don't have that one else madeWithTracker = GetImpulseTrackerVersion(fileHeader.cwtv, 0); - + if(fileHeader.cwtv >= S3MFileHeader::trkIT2_07 && fileHeader.reserved3 != 0) { // Starting from version 2.07, IT stores the total edit time of a module in the "reserved" field @@ -498,15 +515,6 @@ } } - ReadOrderFromFile<uint8>(Order(), file, fileHeader.ordNum, 0xFF, 0xFE); - - // Read sample header offsets - std::vector<uint16le> sampleOffsets; - file.ReadVector(sampleOffsets, fileHeader.smpNum); - // Read pattern offsets - std::vector<uint16le> patternOffsets; - file.ReadVector(patternOffsets, fileHeader.patNum); - // Read extended channel panning if(usePanningTable) { @@ -522,6 +530,7 @@ if(GetNumChannels() < 32 && m_dwLastSavedWithVersion == MPT_V("1.16")) { // MPT 1.0 alpha 6 up to 1.16.203 set the panning bit for all channels, regardless of whether they are used or not. + // Note: Schism Tracker fixed the same bug in git commit f21fe8bcae8b6dde2df27ede4ac9fe563f91baff if(hasChannelsWithoutPanning) m_modFormat.madeWithTracker = UL_("ModPlug Tracker 1.16 / OpenMPT 1.17"); else |