diff --git OpenMPT/soundlib/Load_mod.cpp OpenMPT/soundlib/Load_mod.cpp index 26e12a2..757a3c5 100644 --- OpenMPT/soundlib/Load_mod.cpp +++ OpenMPT/soundlib/Load_mod.cpp @@ -358,6 +358,50 @@ struct PACKED PT36IffChunk STATIC_ASSERT(sizeof(PT36IffChunk) == 8); +struct PACKED PT36InfoChunk +{ + char name[32]; + uint16 numSamples; // unused + uint16 numOrders; // unused + uint16 numPatterns; // unused + uint16 volume; + uint16 tempo; + uint16 flags; // unused + uint16 dateDay; + uint16 dateMonth; + uint16 dateYear; + uint16 dateHour; + uint16 dateMinute; + uint16 dateSecond; + uint16 playtimeHour; // unused + uint16 playtimeMinute; // unused + uint16 playtimeSecond; // unused + uint16 playtimeMsecond; // unused + + // Convert all multi-byte numeric values to current platform's endianness or vice versa. + void ConvertEndianness() + { + SwapBytesBE(numSamples); + SwapBytesBE(numOrders); + SwapBytesBE(numPatterns); + SwapBytesBE(volume); + SwapBytesBE(tempo); + SwapBytesBE(flags); + SwapBytesBE(dateDay); + SwapBytesBE(dateMonth); + SwapBytesBE(dateYear); + SwapBytesBE(dateHour); + SwapBytesBE(dateMinute); + SwapBytesBE(dateSecond); + SwapBytesBE(playtimeHour); + SwapBytesBE(playtimeMinute); + SwapBytesBE(playtimeSecond); + SwapBytesBE(playtimeMsecond); + } +}; + +STATIC_ASSERT(sizeof(PT36InfoChunk) == 64); + #ifdef NEEDS_PRAGMA_PACK #pragma pack(pop) #endif @@ -1441,9 +1485,10 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) return false; } - bool ok = false; + bool ok = false, infoOk = false; std::string title, message; std::string version = "3.6"; + PT36InfoChunk info; // Go through IFF chunks... PT36IffChunk iffHead; @@ -1480,7 +1525,7 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) break; case PT36IffChunk::idINFO: - chunk.ReadString(title, iffHead.chunksize); + infoOk = chunk.ReadConvertEndianness(info); break; case PT36IffChunk::idCMNT: @@ -1493,11 +1538,26 @@ bool CSoundFile::ReadPT36(FileReader &file, ModLoadingFlags loadFlags) } } while(file.CanRead(sizeof(PT36IffChunk)) && file.ReadConvertEndianness(iffHead)); - if(ok) + // both an info chunk and a module are required + if(ok && infoOk) { + m_nSamplePreAmp = MIN(64, info.volume); + m_nDefaultTempo.Set(info.tempo); + + mpt::String::Read(title, info.name); if(!title.empty()) m_songName = title; + FileHistory mptHistory; + MemsetZero(mptHistory.loadDate); + mptHistory.loadDate.tm_year = info.dateYear; + mptHistory.loadDate.tm_mon = Clamp(info.dateMonth, 1, 12) - 1; + mptHistory.loadDate.tm_mday = Clamp(info.dateDay, 1, 31); + mptHistory.loadDate.tm_hour = Clamp(info.dateHour, 0, 23); + mptHistory.loadDate.tm_min = Clamp(info.dateMinute, 0, 59); + mptHistory.loadDate.tm_sec = Clamp(info.dateSecond, 0, 59); + m_FileHistory.push_back(mptHistory); + // "message" chunk seems to only be used to store the artist name, despite being pretty long if(message != "UNNAMED AUTHOR") m_songArtist = mpt::ToUnicode(mpt::CharsetISO8859_1, message);