Index: libopenmpt/bindings/freebasic/libopenmpt.bi =================================================================== --- libopenmpt/bindings/freebasic/libopenmpt.bi (revision 10828) +++ libopenmpt/bindings/freebasic/libopenmpt.bi (working copy) @@ -1037,7 +1037,9 @@ \param key Metadata item key to query. Use openmpt_module_get_metadata_keys to check for available keys. Possible keys are: - type: Module format extension (e.g. it) - - type_long: Tracker name associated with the module format (e.g. Impulse Tracker) + - type_long: Format name associated with the module format (e.g. Impulse Tracker) + - originaltype: Module format extension (e.g. it) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + - originaltype_long: Format name associated with the module format (e.g. Impulse Tracker) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) - container: Container format the module file is embedded in, if any (e.g. umx) - container_long: Full container name if the module is embedded in a container (e.g. Unreal Music) - tracker: Tracker that was (most likely) used to save the module file, if known Index: libopenmpt/dox/changelog.md =================================================================== --- libopenmpt/dox/changelog.md (revision 10828) +++ libopenmpt/dox/changelog.md (working copy) @@ -26,6 +26,9 @@ auto-detection and longer fadeouts. * "stop": Returns 0 rendered frames when the song end is reached. Subsequent reads will return 0 rendered frames. + * [**New**] Add new metadata fields `"originaltype"` and `"originaltype_long"` + which allow more clearly reflecting what is going on with converted formats + like MO3 and GDM. * [**New**] `Makefile` `CONFIG=emscripten` now can generate WebAssembly via the additional option `EMSCRIPTEN_TARGET=wasm`. * [**New**] Compiling for DOS is now experimentally supported via DJGPP GCC Index: libopenmpt/libopenmpt.h =================================================================== --- libopenmpt/libopenmpt.h (revision 10828) +++ libopenmpt/libopenmpt.h (working copy) @@ -1120,7 +1120,9 @@ * \param key Metadata item key to query. Use openmpt_module_get_metadata_keys to check for available keys. * Possible keys are: * - type: Module format extension (e.g. it) - * - type_long: Tracker name associated with the module format (e.g. Impulse Tracker) + * - type_long: Format name associated with the module format (e.g. Impulse Tracker) + * - originaltype: Module format extension (e.g. it) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + * - originaltype_long: Format name associated with the module format (e.g. Impulse Tracker) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) * - container: Container format the module file is embedded in, if any (e.g. umx) * - container_long: Full container name if the module is embedded in a container (e.g. Unreal Music) * - tracker: Tracker that was (most likely) used to save the module file, if known Index: libopenmpt/libopenmpt.hpp =================================================================== --- libopenmpt/libopenmpt.hpp (revision 10828) +++ libopenmpt/libopenmpt.hpp (working copy) @@ -724,7 +724,9 @@ \param key Metadata item key to query. Use openmpt::module::get_metadata_keys to check for available keys. Possible keys are: - type: Module format extension (e.g. it) - - type_long: Tracker name associated with the module format (e.g. Impulse Tracker) + - type_long: Format name associated with the module format (e.g. Impulse Tracker) + - originaltype: Module format extension (e.g. it) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + - originaltype_long: Format name associated with the module format (e.g. Impulse Tracker) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) - container: Container format the module file is embedded in, if any (e.g. umx) - container_long: Full container name if the module is embedded in a container (e.g. Unreal Music) - tracker: Tracker that was (most likely) used to save the module file, if known Index: libopenmpt/libopenmpt_impl.cpp =================================================================== --- libopenmpt/libopenmpt_impl.cpp (revision 10828) +++ libopenmpt/libopenmpt_impl.cpp (working copy) @@ -1100,6 +1100,8 @@ { "type", "type_long", + "originaltype", + "originaltype_long", "container", "container_long", "tracker", @@ -1116,6 +1118,10 @@ return mpt::ToCharset(mpt::CharsetUTF8, m_sndFile->m_modFormat.type ); } else if ( key == std::string("type_long") ) { return mpt::ToCharset(mpt::CharsetUTF8, m_sndFile->m_modFormat.formatName ); + } else if ( key == std::string("originaltype") ) { + return mpt::ToCharset(mpt::CharsetUTF8, m_sndFile->m_modFormat.originalType ); + } else if ( key == std::string("originaltype_long") ) { + return mpt::ToCharset(mpt::CharsetUTF8, m_sndFile->m_modFormat.originalFormatName ); } else if ( key == std::string("container") ) { return mpt::ToCharset(mpt::CharsetUTF8, CSoundFile::ModContainerTypeToString( m_sndFile->GetContainerType() ) ); } else if ( key == std::string("container_long") ) { Index: libopenmpt/libopenmpt_version.h =================================================================== --- libopenmpt/libopenmpt_version.h (revision 10828) +++ libopenmpt/libopenmpt_version.h (working copy) @@ -21,7 +21,7 @@ /*! \brief libopenmpt patch version number */ #define OPENMPT_API_VERSION_PATCH 0 /*! \brief libopenmpt pre-release tag */ -#define OPENMPT_API_VERSION_PREREL "-pre.7" +#define OPENMPT_API_VERSION_PREREL "-pre.8" /*! \brief libopenmpt pre-release flag */ #define OPENMPT_API_VERSION_IS_PREREL 1 Index: libopenmpt/libopenmpt_version.mk =================================================================== --- libopenmpt/libopenmpt_version.mk (revision 10828) +++ libopenmpt/libopenmpt_version.mk (working copy) @@ -1,7 +1,7 @@ LIBOPENMPT_VERSION_MAJOR=0 LIBOPENMPT_VERSION_MINOR=4 LIBOPENMPT_VERSION_PATCH=0 -LIBOPENMPT_VERSION_PREREL=-pre.7 +LIBOPENMPT_VERSION_PREREL=-pre.8 LIBOPENMPT_LTVER_CURRENT=1 LIBOPENMPT_LTVER_REVISION=0 Index: libopenmpt/xmp-openmpt.cpp =================================================================== --- libopenmpt/xmp-openmpt.cpp (revision 10828) +++ libopenmpt/xmp-openmpt.cpp (working copy) @@ -1029,6 +1029,9 @@ str << "\r"; } str << "Format" << "\t" << sanitize_xmplay_info_string( self->mod->get_metadata("type") ) << " (" << sanitize_xmplay_info_string( self->mod->get_metadata("type_long") ) << ")" << "\r"; + if ( !self->mod->get_metadata("originaltype").empty() ) { + str << "Original Type" << "\t" << sanitize_xmplay_info_string( self->mod->get_metadata("originaltype") ) << " (" << sanitize_xmplay_info_string( self->mod->get_metadata("originaltype_long") ) << ")" << "\r"; + } if ( !self->mod->get_metadata("container").empty() ) { str << "Container" << "\t" << sanitize_xmplay_info_string( self->mod->get_metadata("container") ) << " (" << sanitize_xmplay_info_string( self->mod->get_metadata("container_long") ) << ")" << "\r"; } Index: openmpt123/openmpt123.cpp =================================================================== --- openmpt123/openmpt123.cpp (revision 10828) +++ openmpt123/openmpt123.cpp (working copy) @@ -1542,6 +1542,9 @@ set_field( fields, "Container" ).ostream() << mod.get_metadata( "container" ) << " (" << mod.get_metadata( "container_long" ) << ")"; } set_field( fields, "Type" ).ostream() << mod.get_metadata( "type" ) << " (" << mod.get_metadata( "type_long" ) << ")"; + if ( !mod.get_metadata( "originaltype" ).empty() ) { + set_field( fields, "Orig. Type" ).ostream() << mod.get_metadata( "originaltype" ) << " (" << mod.get_metadata( "originaltype_long" ) << ")"; + } if ( ( mod.get_num_subsongs() > 1 ) && ( flags.subsong != -1 ) ) { set_field( fields, "Subsong" ).ostream() << flags.subsong; } Index: soundlib/Load_gdm.cpp =================================================================== --- soundlib/Load_gdm.cpp (revision 10828) +++ soundlib/Load_gdm.cpp (working copy) @@ -94,10 +94,23 @@ { MOD_TYPE_NONE, MOD_TYPE_MOD, MOD_TYPE_MTM, MOD_TYPE_S3M, MOD_TYPE_669, MOD_TYPE_FAR, MOD_TYPE_ULT, MOD_TYPE_STM, MOD_TYPE_MED, MOD_TYPE_PSM }; -static const char gdmFormatOriginStr[][4] = +static const MPT_UCHAR_TYPE gdmFormatOriginType[][4] = { - "???", "MOD", "MTM", "S3M", "669", "FAR", "ULT", "STM", "MED", "PSM" + MPT_ULITERAL(""), MPT_ULITERAL("mod"), MPT_ULITERAL("mtm"), MPT_ULITERAL("s3m"), MPT_ULITERAL("669"), MPT_ULITERAL("far"), MPT_ULITERAL("ult"), MPT_ULITERAL("stm"), MPT_ULITERAL("med"), MPT_ULITERAL("psm") }; +static const MPT_UCHAR_TYPE * const gdmFormatOriginFormat[] = +{ + MPT_ULITERAL(""), + MPT_ULITERAL("Generic MOD"), + MPT_ULITERAL("MultiTracker"), + MPT_ULITERAL("ScreamTracker 3"), + MPT_ULITERAL("Composer 669 / UNIS 669"), + MPT_ULITERAL("Farandole Composer"), + MPT_ULITERAL("UltraTracker"), + MPT_ULITERAL("ScreamTracker 2"), + MPT_ULITERAL("OctaMED"), + MPT_ULITERAL("Epic Megagames MASI") +}; static bool ValidateHeader(const GDMFileHeader &fileHeader) @@ -153,9 +166,10 @@ m_modFormat.formatName = MPT_USTRING("General Digital Music"); m_modFormat.type = MPT_USTRING("gdm"); - m_modFormat.madeWithTracker = mpt::format(MPT_USTRING("BWSB 2GDM %1.%2 (converted from %3)"))(fileHeader.trackerMajorVer, fileHeader.formatMinorVer, mpt::ToUnicode(mpt::CharsetASCII, gdmFormatOriginStr[fileHeader.originalFormat])); + m_modFormat.madeWithTracker = mpt::format(MPT_USTRING("BWSB 2GDM %1.%2"))(fileHeader.trackerMajorVer, fileHeader.formatMinorVer); + m_modFormat.originalType = gdmFormatOriginType[fileHeader.originalFormat]; + m_modFormat.originalFormatName = gdmFormatOriginFormat[fileHeader.originalFormat]; m_modFormat.charset = mpt::CharsetCP437; - m_ContainerType = MOD_CONTAINERTYPE_GDM; // Song name mpt::String::Read(m_songName, fileHeader.songTitle); Index: soundlib/Load_it.cpp =================================================================== --- soundlib/Load_it.cpp (revision 10828) +++ soundlib/Load_it.cpp (working copy) @@ -2332,7 +2332,7 @@ } -void CSoundFile::LoadExtendedSongProperties(FileReader &file, bool *pInterpretMptMade) +void CSoundFile::LoadExtendedSongProperties(FileReader &file, bool *pInterpretMptMade, bool isMO3) { if(!file.ReadMagic("STPM")) // 'MPTS' { @@ -2370,7 +2370,7 @@ case MagicBE("RPB."): ReadField(chunk, size, m_nDefaultRowsPerBeat); break; case MagicBE("RPM."): ReadField(chunk, size, m_nDefaultRowsPerMeasure); break; // FIXME: If there are only PC events on the last few channels in an MPTM MO3, they won't be imported! - case MagicBE("C..."): if(GetType() != MOD_TYPE_XM && m_ContainerType != MOD_CONTAINERTYPE_MO3) { CHANNELINDEX chn = 0; ReadField(chunk, size, chn); m_nChannels = Clamp(chn, m_nChannels, MAX_BASECHANNELS); } break; + case MagicBE("C..."): if(GetType() != MOD_TYPE_XM && !isMO3) { CHANNELINDEX chn = 0; ReadField(chunk, size, chn); m_nChannels = Clamp(chn, m_nChannels, MAX_BASECHANNELS); } break; case MagicBE("TM.."): ReadFieldCast(chunk, size, m_nTempoMode); break; case MagicBE("PMM."): ReadFieldCast(chunk, size, m_nMixLevels); break; case MagicBE("CWV."): { uint32 ver = 0; ReadField(chunk, size, ver); m_dwCreatedWithVersion = Version(ver); break; } Index: soundlib/Load_mo3.cpp =================================================================== --- soundlib/Load_mo3.cpp (revision 10828) +++ soundlib/Load_mo3.cpp (working copy) @@ -800,34 +800,33 @@ m_nDefaultSpeed = fileHeader.defaultSpeed ? fileHeader.defaultSpeed : 6; m_nDefaultTempo.Set(fileHeader.defaultTempo ? fileHeader.defaultTempo : 125, 0); - m_ContainerType = MOD_CONTAINERTYPE_MO3; - mpt::ustring formatType; - mpt::ustring formatName; + mpt::ustring originalFormatType; + mpt::ustring originalFormatName; if(fileHeader.flags & MO3FileHeader::isIT) { SetType(MOD_TYPE_IT); - formatType = MPT_USTRING("it"); - formatName = MPT_USTRING("Impulse Tracker"); + originalFormatType = MPT_USTRING("it"); + originalFormatName = MPT_USTRING("Impulse Tracker"); } else if(fileHeader.flags & MO3FileHeader::isS3M) { SetType(MOD_TYPE_S3M); - formatType = MPT_USTRING("s3m"); - formatName = MPT_USTRING("ScreamTracker 3"); + originalFormatType = MPT_USTRING("s3m"); + originalFormatName = MPT_USTRING("ScreamTracker 3"); } else if(fileHeader.flags & MO3FileHeader::isMOD) { SetType(MOD_TYPE_MOD); - formatType = MPT_USTRING("mod"); - formatName = MPT_USTRING("Generic MOD"); + originalFormatType = MPT_USTRING("mod"); + originalFormatName = MPT_USTRING("Generic MOD"); } else if(fileHeader.flags & MO3FileHeader::isMTM) { SetType(MOD_TYPE_MTM); - formatType = MPT_USTRING("mtm"); - formatName = MPT_USTRING("MultiTracker"); + originalFormatType = MPT_USTRING("mtm"); + originalFormatName = MPT_USTRING("MultiTracker"); } else { SetType(MOD_TYPE_XM); - formatType = MPT_USTRING("xm"); - formatName = MPT_USTRING("FastTracker 2"); + originalFormatType = MPT_USTRING("xm"); + originalFormatName = MPT_USTRING("FastTracker 2"); } if(fileHeader.flags & MO3FileHeader::linearSlides) @@ -1844,7 +1843,7 @@ } LoadExtendedInstrumentProperties(chunk); - LoadExtendedSongProperties(chunk); + LoadExtendedSongProperties(chunk, nullptr, true); if(cwtv > 0x0889 && cwtv <= 0x8FF) { m_nType = MOD_TYPE_MPT; @@ -1872,8 +1871,10 @@ else madeWithTracker = mpt::format(MPT_USTRING("MO3 v%1 (%2)"))(version, madeWithTracker); - m_modFormat.formatName = mpt::format(MPT_USTRING("%1 (MO3 v%2 packed)"))(formatName, version); - m_modFormat.type = std::move(formatType); + m_modFormat.formatName = mpt::format(MPT_USTRING("Un4seen MO3 v%1"))(version); + m_modFormat.type = MPT_USTRING("mo3"); + m_modFormat.originalType = std::move(originalFormatType); + m_modFormat.originalFormatName = std::move(originalFormatName); m_modFormat.madeWithTracker = std::move(madeWithTracker); if(m_dwLastSavedWithVersion) m_modFormat.charset = mpt::CharsetWindows1252; Index: soundlib/Snd_defs.h =================================================================== --- soundlib/Snd_defs.h (revision 10828) +++ soundlib/Snd_defs.h (working copy) @@ -105,8 +105,6 @@ enum MODCONTAINERTYPE { MOD_CONTAINERTYPE_NONE = 0x0, - MOD_CONTAINERTYPE_MO3 = 0x1, - MOD_CONTAINERTYPE_GDM = 0x2, MOD_CONTAINERTYPE_UMX = 0x3, MOD_CONTAINERTYPE_XPK = 0x4, MOD_CONTAINERTYPE_PP20 = 0x5, Index: soundlib/Sndfile.h =================================================================== --- soundlib/Sndfile.h (revision 10828) +++ soundlib/Sndfile.h (working copy) @@ -247,9 +247,11 @@ struct ModFormatDetails { - mpt::ustring formatName; // "FastTracker 2" - mpt::ustring type; // "xm" - mpt::ustring madeWithTracker; // "OpenMPT 1.28.01.00" + mpt::ustring formatName; // "FastTracker 2" + mpt::ustring type; // "xm" + mpt::ustring madeWithTracker; // "OpenMPT 1.28.01.00" + mpt::ustring originalFormatName; // "FastTracker 2" in the case of converted formats like MO3 or GDM + mpt::ustring originalType; // "xm" in the case of converted formats like MO3 or GDM mpt::Charset charset = mpt::CharsetUTF8; }; @@ -811,7 +813,7 @@ void SaveExtendedInstrumentProperties(INSTRUMENTINDEX nInstruments, std::ostream &f) const; void SaveExtendedSongProperties(std::ostream &f) const; #endif // MODPLUG_NO_FILESAVE - void LoadExtendedSongProperties(FileReader &file, bool* pInterpretMptMade = nullptr); + void LoadExtendedSongProperties(FileReader &file, bool* pInterpretMptMade = nullptr, bool isMNO3 = false); void LoadMPTMProperties(FileReader &file, uint16 cwtv); mpt::ustring GetSchismTrackerVersion(uint16 cwtv); Index: soundlib/Tables.cpp =================================================================== --- soundlib/Tables.cpp (revision 10828) +++ soundlib/Tables.cpp (working copy) @@ -94,6 +94,9 @@ { MOD_TYPE_STP, MPT_ULITERAL("Soundtracker Pro II"), "stp" }, { MOD_TYPE_ULT, MPT_ULITERAL("UltraTracker"), "ult" }, { MOD_TYPE_MOD, MPT_ULITERAL("Grave Composer"), "wow" }, + // converted formats (no MODTYPE) + { MOD_TYPE_NONE, MPT_ULITERAL("General Digital Music"), "gdm" }, + { MOD_TYPE_NONE, MPT_ULITERAL("Un4seen MO3"), "mo3" }, #ifndef NO_ARCHIVE_SUPPORT // Compressed modules { MOD_TYPE_MOD, MPT_ULITERAL("Compressed ProTracker"), "mdz" }, @@ -116,9 +119,7 @@ static constexpr ModContainerInfo modContainerInfo[] = { // Container formats - { MOD_CONTAINERTYPE_GDM, MPT_ULITERAL("General Digital Music"), "gdm" }, { MOD_CONTAINERTYPE_UMX, MPT_ULITERAL("Unreal Music"), "umx" }, - { MOD_CONTAINERTYPE_MO3, MPT_ULITERAL("Un4seen MO3"), "mo3" }, { MOD_CONTAINERTYPE_XPK, MPT_ULITERAL("XPK packed"), "xpk" }, { MOD_CONTAINERTYPE_PP20, MPT_ULITERAL("PowerPack PP20"), "ppm" }, { MOD_CONTAINERTYPE_MMCMP, MPT_ULITERAL("Music Module Compressor"), "mmcmp" }