Index: libopenmpt/bindings/freebasic/libopenmpt.bi
===================================================================
--- libopenmpt/bindings/freebasic/libopenmpt.bi	(revision 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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 10844)
+++ 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<mpt::String::maybeNullTerminated>(m_songName, fileHeader.songTitle);
Index: soundlib/Load_mo3.cpp
===================================================================
--- soundlib/Load_mo3.cpp	(revision 10844)
+++ 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)
@@ -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 10844)
+++ 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 10844)
+++ 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;
 };
 
Index: soundlib/Tables.cpp
===================================================================
--- soundlib/Tables.cpp	(revision 10844)
+++ 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" }
