View Issue Details

IDProjectCategoryView StatusLast Update
0000741OpenMPT[All Projects] File Format Supportpublic2016-07-31 12:47
ReporterncovertAssigned ToSaga Musix 
PrioritynormalSeverityfeatureReproducibilityN/A
Status resolvedResolutionfixed 
Platformx64OSWindowsOS Version7
Product VersionOpenMPT 1.25.04.00 / libopenmpt 0.2-beta16 (upgrade first) 
Target VersionOpenMPT 1.26.01.00 / libopenmpt 0.2-beta17 (upgrade first)Fixed in VersionOpenMPT 1.26.01.00 / libopenmpt 0.2-beta17 (upgrade first) 
Summary0000741: Add support for SoundFX modules
Description

SoundFX is a Soundtracker clone. It saves in the SFX file format. It is similar to MOD, though I believe the C-5 sample rate is different and it allows for a default speed/tempo other than 125/6, so it may need to be converted to S3M when opened in MPT.

TagsNo tags attached.
Has the bug occurred in previous versions?
Tested code revision (in case you know it)

Activities

Revenant

Revenant

2016-03-09 03:14

reporter   ~0002277

Last edited: 2016-03-09 03:38

View 3 revisions

Since I'm on a bit of a file-format kick lately, I decided to take this one on as well. I gleaned some info about effects from Flod's SoundFX player, but otherwise this is largely based on the Soundtracker loader. Both 15- and 31-sample modules are supported (apparently the latter often use the name "MultiMedia Sound" which as far as I can tell is just SoundFX 2.0).

This is a work in progress, so some things might not sound 100% right (but the modules I've tried so far sound pretty much correct).

In addition to the patch, here's a (64-bit) Windows build of openmpt123 with the SoundFX support added:
https://dl.dropboxusercontent.com/u/43107309/openmpt-soundfx.zip
(I don't have the means to build mptrack or the winamp/xmplay plugins at the moment, sorry)

(edit: reuploaded new patch to correct a sloppy mistake I caught immediately after uploading the first one, whoops)

ncovert

ncovert

2016-03-09 20:14

reporter   ~0002278

Last edited: 2016-03-09 20:16

View 3 revisions

The openmpt123 build works perfectly with SoundFX modules! How would I go about applying the PATCH file?

Revenant

Revenant

2016-03-10 01:58

reporter   ~0002279

Last edited: 2016-03-10 01:58

View 2 revisions

Uploaded a new patch (and build), changes:

  • Changed how total number of saved patterns is determined (fixes "19remix.sfx")
  • Removed 64-pattern limit (fixes "amc-slideshow.sfx")
  • Changed how 7xx/8xx effects work across pattern boundaries (fixes "sonic depth finder.mms" by Roman Werner, probably others)
  • Removed handling of 9xx effects (Flod treats this as a tone portamento, but none of the versions of SoundFX / MultiMedia Sound that I have seem to actually do anything with this effect, so now the loader just ignores it)

There are a few ways to apply patch files on Windows. If you use TortoiseSVN then it should work if you do this:
https://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-patch.html

Note that if you build with Visual Studio, you'll have to add soundlib/Load_sfx.cpp to the project yourself.

ncovert

ncovert

2016-03-10 02:29

reporter   ~0002280

I'm not a programmer, and even with those directions, I have no clue how to use TortoiseSVN to patch the file. As a result, I will have to wait until an actual release arrives.

Revenant

Revenant

2016-03-10 03:51

reporter   ~0002281

Ah, all right.

Anyway, added yet another revision of the patch, which just fixes another little mistake after I reread Flod's .sfx player and the actual SoundFX 1.8 replay source (but it shouldn't affect very many, if any, existing modules). New build is in the same place. Hopefully this should be the last revision but I still haven't tried every single .sfx/.mms file that I have (or listened to most of them in the original tracker for that matter).

(Apologies for uploading so many minor revisions of the same patch this time. Would be nice if I could delete old attachments, but there doesn't seem to be a way to...)

Revenant

Revenant

2016-03-10 03:51

reporter  

sfx_r4.patch (15,283 bytes)
diff --git OpenMPT/build/android_ndk/Android-minimp3-stbvorbis.mk OpenMPT/build/android_ndk/Android-minimp3-stbvorbis.mk
index 7ec6552..4c0be60 100644
--- OpenMPT/build/android_ndk/Android-minimp3-stbvorbis.mk
+++ OpenMPT/build/android_ndk/Android-minimp3-stbvorbis.mk
@@ -73,6 +73,7 @@ LOCAL_SRC_FILES := \
 	soundlib/Load_psm.cpp \
 	soundlib/Load_ptm.cpp \
 	soundlib/Load_s3m.cpp \
+	soundlib/Load_sfx.cpp \
 	soundlib/Load_stm.cpp \
 	soundlib/Load_ult.cpp \
 	soundlib/Load_umx.cpp \
diff --git OpenMPT/build/android_ndk/Android-mpg123-vorbis.mk OpenMPT/build/android_ndk/Android-mpg123-vorbis.mk
index 0c09b5e..0b1d8e6 100644
--- OpenMPT/build/android_ndk/Android-mpg123-vorbis.mk
+++ OpenMPT/build/android_ndk/Android-mpg123-vorbis.mk
@@ -71,6 +71,7 @@ LOCAL_SRC_FILES := \
 	soundlib/Load_psm.cpp \
 	soundlib/Load_ptm.cpp \
 	soundlib/Load_s3m.cpp \
+	soundlib/Load_sfx.cpp \
 	soundlib/Load_stm.cpp \
 	soundlib/Load_ult.cpp \
 	soundlib/Load_umx.cpp \
diff --git OpenMPT/build/android_ndk/Android-unmo3.mk OpenMPT/build/android_ndk/Android-unmo3.mk
index f28d829..0f89ca3 100644
--- OpenMPT/build/android_ndk/Android-unmo3.mk
+++ OpenMPT/build/android_ndk/Android-unmo3.mk
@@ -104,6 +104,7 @@ LOCAL_SRC_FILES := \
 	soundlib/Load_psm.cpp \
 	soundlib/Load_ptm.cpp \
 	soundlib/Load_s3m.cpp \
+	soundlib/Load_sfx.cpp \
 	soundlib/Load_stm.cpp \
 	soundlib/Load_ult.cpp \
 	soundlib/Load_umx.cpp \
diff --git OpenMPT/build/android_ndk/Android.mk OpenMPT/build/android_ndk/Android.mk
index 6ef628b..f5214ca 100644
--- OpenMPT/build/android_ndk/Android.mk
+++ OpenMPT/build/android_ndk/Android.mk
@@ -72,6 +72,7 @@ LOCAL_SRC_FILES := \
 	soundlib/Load_psm.cpp \
 	soundlib/Load_ptm.cpp \
 	soundlib/Load_s3m.cpp \
+	soundlib/Load_sfx.cpp \
 	soundlib/Load_stm.cpp \
 	soundlib/Load_ult.cpp \
 	soundlib/Load_umx.cpp \
diff --git OpenMPT/build/autotools/Makefile.am OpenMPT/build/autotools/Makefile.am
index 86dbdd2..afdb965 100644
--- OpenMPT/build/autotools/Makefile.am
+++ OpenMPT/build/autotools/Makefile.am
@@ -184,6 +184,7 @@ libopenmpt_la_SOURCES += soundlib/Load_plm.cpp
 libopenmpt_la_SOURCES += soundlib/Load_psm.cpp
 libopenmpt_la_SOURCES += soundlib/Load_ptm.cpp
 libopenmpt_la_SOURCES += soundlib/Load_s3m.cpp
+libopenmpt_la_SOURCES += soundlib/Load_sfx.cpp
 libopenmpt_la_SOURCES += soundlib/Load_stm.cpp
 libopenmpt_la_SOURCES += soundlib/Load_ult.cpp
 libopenmpt_la_SOURCES += soundlib/Load_umx.cpp
@@ -417,6 +418,7 @@ libopenmpttest_SOURCES += soundlib/Load_plm.cpp
 libopenmpttest_SOURCES += soundlib/Load_psm.cpp
 libopenmpttest_SOURCES += soundlib/Load_ptm.cpp
 libopenmpttest_SOURCES += soundlib/Load_s3m.cpp
+libopenmpttest_SOURCES += soundlib/Load_sfx.cpp
 libopenmpttest_SOURCES += soundlib/Load_stm.cpp
 libopenmpttest_SOURCES += soundlib/Load_ult.cpp
 libopenmpttest_SOURCES += soundlib/Load_umx.cpp
diff --git OpenMPT/libopenmpt/foo_openmpt.cpp OpenMPT/libopenmpt/foo_openmpt.cpp
index ac7ce34..4517eff 100644
--- OpenMPT/libopenmpt/foo_openmpt.cpp
+++ OpenMPT/libopenmpt/foo_openmpt.cpp
@@ -319,6 +319,9 @@ DECLARE_FILE_TYPE("OpenMPT compatible module files",
 	"*.imf" ";"
 	"*.j2b" ";"
 	"*.plm" ";"
+	"*.sfx" ";"
+	"*.sfx2" ";"
+	"*.mms" ";"
 	"*.gdm" ";"
 	"*.umx" ";"
 	"*.mo3" ";"
diff --git OpenMPT/soundlib/Load_sfx.cpp OpenMPT/soundlib/Load_sfx.cpp
new file mode 100644
index 0000000..884dc8c
--- /dev/null
+++ OpenMPT/soundlib/Load_sfx.cpp
@@ -0,0 +1,381 @@
+/*
+ * Load_sfx.cpp
+ * ------------
+ * Purpose: SFX / MMS (SoundFX / MultiMedia Sound) module loader
+ * Notes  : Mostly based on the Soundtracker loader, some effect behavior is based on Flod's implementation.
+ * Authors: Devin Acker
+ *          OpenMPT Devs
+ * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
+ */
+
+#include "stdafx.h"
+#include "Loaders.h"
+#include "Tables.h"
+
+OPENMPT_NAMESPACE_BEGIN
+
+#ifdef NEEDS_PRAGMA_PACK
+#pragma pack(push, 1)
+#endif
+
+// File Header
+struct PACKED SFXFileHeader
+{
+	uint8 numOrders;
+	uint8 restartPos;
+	uint8 orderList[128];
+};
+
+STATIC_ASSERT(sizeof(SFXFileHeader) == 130);
+
+// Sample Header
+struct PACKED SFXSampleHeader
+{
+	char   name[22];
+	uint16 dummy; // supposedly sample length, but almost always incorrect
+	uint8  finetune;
+	uint8  volume;
+	uint16 loopStart;
+	uint16 loopLength;
+
+	// Convert all multi-byte numeric values to current platform's endianness or vice versa.
+	void ConvertEndianness()
+	{
+		SwapBytesBE(loopStart);
+		SwapBytesBE(loopLength);
+	}
+
+	// Convert an MOD sample header to OpenMPT's internal sample header.
+	void ConvertToMPT(ModSample &mptSmp, uint32 length) const
+	{
+		mptSmp.Initialize(MOD_TYPE_MOD);
+		mptSmp.nLength = static_cast<SmpLength>(length);
+		mptSmp.nFineTune = MOD2XMFineTune(finetune & 0x0F);
+		mptSmp.nVolume = 4 * MIN(volume, 64);
+
+		SmpLength lStart = loopStart;
+		SmpLength lLength = loopLength * 2;
+
+		if(mptSmp.nLength)
+		{
+			mptSmp.nLoopStart = lStart;
+			mptSmp.nLoopEnd = lStart + lLength;
+
+			if(mptSmp.nLoopStart >= mptSmp.nLength)
+			{
+				mptSmp.nLoopStart = mptSmp.nLength - 1;
+			}
+			if(mptSmp.nLoopEnd > mptSmp.nLength)
+			{
+				mptSmp.nLoopEnd = mptSmp.nLength;
+			}
+			if(mptSmp.nLoopStart > mptSmp.nLoopEnd || mptSmp.nLoopEnd < 4 || mptSmp.nLoopEnd - mptSmp.nLoopStart < 4)
+			{
+				mptSmp.nLoopStart = 0;
+				mptSmp.nLoopEnd = 0;
+			}
+
+			if(mptSmp.nLoopEnd > mptSmp.nLoopStart)
+			{
+				mptSmp.uFlags.set(CHN_LOOP);
+			}
+		}
+	}
+};
+
+STATIC_ASSERT(sizeof(SFXSampleHeader) == 30);
+
+#ifdef NEEDS_PRAGMA_PACK
+#pragma pack(pop)
+#endif
+
+static uint32 ReadSample(FileReader &file, SFXSampleHeader &sampleHeader, uint32 length, ModSample &sample, char (&sampleName)[MAX_SAMPLENAME])
+//------------------------------------------------------------------------------------------------------------------------------
+{
+	file.ReadConvertEndianness(sampleHeader);
+	sampleHeader.ConvertToMPT(sample, length);
+
+	mpt::String::Read<mpt::String::spacePadded>(sampleName, sampleHeader.name);
+	// Get rid of weird characters in sample names.
+	uint32 invalidChars = 0;
+	for(uint32 i = 0; i < CountOf(sampleName); i++)
+	{
+		if(sampleName[i] > 0 && sampleName[i] < ' ')
+		{
+			sampleName[i] = ' ';
+			invalidChars++;
+		}
+	}
+	return invalidChars;
+}
+
+bool CSoundFile::ReadSFX(FileReader &file, ModLoadingFlags loadFlags)
+//-------------------------------------------------------------------
+{
+	if(file.Seek(0x3C), file.ReadMagic("SONG"))
+	{
+		InitializeGlobals(MOD_TYPE_SFX);
+		m_nSamples = 15;
+	} else if(file.Seek(0x7C), file.ReadMagic("SO31"))
+	{
+		InitializeGlobals(MOD_TYPE_SFX);
+		m_nSamples = 31;
+	} else
+	{
+		return false;
+	}
+	
+	size_t totalSampleLen = 0;
+	uint32 sampleLen[31];
+	
+	file.Rewind();
+	for(SAMPLEINDEX smp = 0; smp < m_nSamples; smp++)
+	{
+		sampleLen[smp] = file.ReadUint32BE();
+		if(sampleLen[smp] > 65535)
+			return false;
+			
+		totalSampleLen += sampleLen[smp];
+	}
+	
+	m_nChannels = 4;
+	m_nInstruments = 0;
+	m_nDefaultSpeed = 6;
+	m_nMinPeriod = 14 * 4;
+	m_nMaxPeriod = 3424 * 4;
+	m_nSamplePreAmp = 64;
+	m_SongFlags.reset();
+
+	// Setup channel pan positions and volume
+	SetupMODPanning(true);
+	
+	file.Skip(4);
+	uint16 speed = file.ReadUint16BE();
+	m_nDefaultTempo = TEMPO(14565.0 * 122 / speed);
+	
+	file.Skip(14);
+	
+	for(SAMPLEINDEX smp = 1; smp <= m_nSamples; smp++)
+	{
+		SFXSampleHeader sampleHeader;
+		ReadSample(file, sampleHeader, sampleLen[smp-1], Samples[smp], m_szNames[smp]);
+	}
+	
+	SFXFileHeader fileHeader;
+	file.ReadStruct(fileHeader);
+
+	if(fileHeader.numOrders > 128)
+		return false;
+
+	PATTERNINDEX numPatterns = 0;
+	for(ORDERINDEX ord = 0; ord < fileHeader.numOrders; ord++)
+	{
+		numPatterns = MAX(numPatterns, fileHeader.orderList[ord]+1);
+	}
+	
+	if(loadFlags == onlyVerifyHeader)
+		return true;
+	
+	if(fileHeader.restartPos < fileHeader.numOrders)
+		Order.SetRestartPos(fileHeader.restartPos);
+	else
+		Order.SetRestartPos(0);
+	
+	Order.ReadFromArray(fileHeader.orderList);
+	Order.resize(fileHeader.numOrders);
+	
+	// SFX v2 / MMS modules have 4 extra bytes here for some reason
+	if(m_nSamples == 31)
+		file.Skip(4);
+	
+	uint8 lastNote[4] = {0};
+	uint8 slideTo[4] = {0};
+	uint8 slideRate[4] = {0};
+		
+	// Reading patterns
+	for(PATTERNINDEX pat = 0; pat < numPatterns; pat++)
+	{
+		if(!(loadFlags & loadPatternData) || !Patterns.Insert(pat, 64))
+		{
+			file.Skip(64 * 4 * 4);
+			continue;
+		}
+
+		for(ROWINDEX row = 0; row < 64; row++)
+		{
+			PatternRow rowBase = Patterns[pat].GetpModCommand(row, 0);
+			for(CHANNELINDEX chn = 0; chn < 4; chn++)
+			{
+				ModCommand &m = rowBase[chn];
+				uint8 data[4];
+				file.ReadArray(data);
+
+				if(data[0] == 0xFF)
+				{
+					m.note = NOTE_NONE;
+					m.instr = m.command = m.param = 0;
+					lastNote[chn] = slideRate[chn] = 0;
+					
+					switch(data[1])
+					{
+					case 0xFE: // STP (note cut)
+						m.command = CMD_VOLUME;
+						continue;
+						
+					case 0xFD: // PIC (null)
+						continue;
+						
+					case 0xFC: // BRK (pattern break)
+						m.command = CMD_PATTERNBREAK;
+						continue;
+					}
+				} 
+			
+				// Read Period
+				uint16 period = (((static_cast<uint16>(data[0]) & 0x0F) << 8) | data[1]);
+				m.note = NOTE_NONE;
+				if(period > 0 && period != 0xFFF)
+				{
+					m.note = 6 * 12 + 35 + NOTE_MIN;
+					for(int i = 0; i < 6 * 12; i++)
+					{
+						if(period >= ProTrackerPeriodTable[i])
+						{
+							if(period != ProTrackerPeriodTable[i] && i != 0)
+							{
+								uint16 p1 = ProTrackerPeriodTable[i - 1];
+								uint16 p2 = ProTrackerPeriodTable[i];
+								if(p1 - period < (period - p2))
+								{
+									m.note = static_cast<ModCommand::NOTE>(i + 35 + NOTE_MIN);
+									break;
+								}
+							}
+							m.note = static_cast<ModCommand::NOTE>(i + 36 + NOTE_MIN);
+							break;
+						}
+					}
+				}
+				// Read Instrument
+				m.instr = (data[2] >> 4) | (data[0] & 0x10);
+				// Read Effect
+				m.command = data[2] & 0x0F;
+				m.param = data[3];
+				
+				if(m.note)
+				{
+					lastNote[chn] = m.note;
+					slideRate[chn] = 0;
+				}
+				
+				if(m.command || m.param)
+				{
+					switch(m.command)
+					{
+					case 0x1: // arpeggio
+						m.command = CMD_ARPEGGIO;
+						break;
+						
+					case 0x2: // portamento (like Ultimate Soundtracker)
+						if(m.param & 0xF0)
+						{
+							m.command = CMD_PORTAMENTODOWN;
+							m.param >>= 4;
+						} else if(m.param & 0xF)
+						{
+							m.command = CMD_PORTAMENTOUP;
+							m.param &= 0x0F;
+						} else
+						{
+							m.command = m.param = 0;
+						}
+						break;
+						
+					case 0x3: // enable filter/LED
+						m.command = CMD_MODCMDEX;
+						m.param = 0;
+						break;
+						
+					case 0x4: // disable filter/LED
+						m.command = CMD_MODCMDEX;
+						m.param = 1;
+						break;
+						
+					case 0x5: // increase volume
+						if(m.instr)
+						{
+							m.command = CMD_VOLUME;
+							m.param = MIN(0x3F, (Samples[m.instr].nVolume >> 2) + m.param);
+						} else
+						{
+							m.command = m.param = 0;
+						}
+						break;
+					
+					case 0x6: // decrease volume
+						if(m.instr)
+						{
+							m.command = CMD_VOLUME;
+							if((Samples[m.instr].nVolume >> 2) >= m.param)
+								m.param = (Samples[m.instr].nVolume >> 2) - m.param;
+							else
+								m.param = 0;
+						} else
+						{
+							m.command = m.param = 0;
+						}
+						break;
+						
+					case 0x7: // 7xy: slide down x semitones at speed y
+						slideTo[chn] = lastNote[chn] - (m.param >> 4);
+						
+						m.command = CMD_PORTAMENTODOWN;
+						m.param = slideRate[chn] = m.param & 0xF;
+						break;
+						
+					case 0x8: // 8xy: slide up x semitones at speed y
+						slideTo[chn] = lastNote[chn] + (m.param >> 4);
+						
+						m.command = CMD_PORTAMENTOUP;
+						m.param = slideRate[chn] = m.param & 0xF;
+						break;
+					
+					default:
+						m.command = m.param = 0;
+						break;
+					}
+				}
+				
+				// continue 7xy/8xy slides if needed
+				if(!m.command && slideRate[chn])
+				{
+					if(slideTo[chn])
+					{
+						m.note = lastNote[chn] = slideTo[chn];
+						m.param = slideRate[chn];
+						slideTo[chn] = 0;
+					}
+					m.command = CMD_TONEPORTAMENTO;
+				}
+			}
+		}
+	}
+	
+	// Reading samples
+	if(loadFlags & loadSampleData)
+	{
+		for(SAMPLEINDEX smp = 1; smp <= m_nSamples; smp++) if(Samples[smp].nLength)
+		{
+			SampleIO(
+				SampleIO::_8bit,
+				SampleIO::mono,
+				SampleIO::littleEndian,
+				SampleIO::signedPCM)
+				.ReadSample(Samples[smp], file);
+		}
+	}
+	
+	return true;
+}
+
+OPENMPT_NAMESPACE_END
diff --git OpenMPT/soundlib/Snd_defs.h OpenMPT/soundlib/Snd_defs.h
index 4499f0b..398132e 100644
--- OpenMPT/soundlib/Snd_defs.h
+++ OpenMPT/soundlib/Snd_defs.h
@@ -97,6 +97,7 @@ enum MODTYPE
 	MOD_TYPE_DIGI	= 0x8000000,
 	MOD_TYPE_UAX	= 0x10000000, // sampleset as module
 	MOD_TYPE_PLM	= 0x20000000,
+	MOD_TYPE_SFX	= 0x40000000,
 };
 DECLARE_FLAGSET(MODTYPE)
 
diff --git OpenMPT/soundlib/Sndfile.cpp OpenMPT/soundlib/Sndfile.cpp
index d85039d..8c61101 100644
--- OpenMPT/soundlib/Sndfile.cpp
+++ OpenMPT/soundlib/Sndfile.cpp
@@ -313,6 +313,7 @@ bool CSoundFile::Create(FileReader file, ModLoadingFlags loadFlags)
 		 && !ReadMod(file, loadFlags)
 		 && !Read669(file, loadFlags)
 		 && !ReadICE(file, loadFlags)
+		 && !ReadSFX(file, loadFlags)
 		 && !ReadM15(file, loadFlags))
 		{
 			m_nType = MOD_TYPE_NONE;
@@ -1041,6 +1042,7 @@ MODTYPE CSoundFile::GetBestSaveFormat() const
 		return GetType();
 	case MOD_TYPE_AMF0:
 	case MOD_TYPE_DIGI:
+	case MOD_TYPE_SFX:
 		return MOD_TYPE_MOD;
 	case MOD_TYPE_MED:
 		if(m_nDefaultTempo == TEMPO(125, 0) && m_nDefaultSpeed == 6 && !m_nInstruments)
diff --git OpenMPT/soundlib/Sndfile.h OpenMPT/soundlib/Sndfile.h
index eee6e13..ab655e9 100644
--- OpenMPT/soundlib/Sndfile.h
+++ OpenMPT/soundlib/Sndfile.h
@@ -669,6 +669,7 @@ public:
 	bool ReadDIGI(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
 	bool ReadPLM(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
 	bool ReadMID(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
+	bool ReadSFX(FileReader &file, ModLoadingFlags loadFlags = loadCompleteModule);
 
 	static std::vector<const char *> GetSupportedExtensions(bool otherFormats);
 	static mpt::Charset GetCharsetFromModType(MODTYPE modtype);
diff --git OpenMPT/soundlib/Tables.cpp OpenMPT/soundlib/Tables.cpp
index abf91a9..ab1dd15 100644
--- OpenMPT/soundlib/Tables.cpp
+++ OpenMPT/soundlib/Tables.cpp
@@ -87,6 +87,9 @@ static const ModFormatInfo modFormatInfo[] =
 	{ MOD_TYPE_IMF,		"Imago Orpheus",			"imf" },
 	{ MOD_TYPE_J2B,		"Galaxy Sound System",		"j2b" },
 	{ MOD_TYPE_PLM,		"Disorder Tracker 2",		"plm" },
+	{ MOD_TYPE_SFX,		"SoundFX",					"sfx" },
+	{ MOD_TYPE_SFX,		"SoundFX",					"sfx2" },
+	{ MOD_TYPE_SFX,		"MultiMedia Sound",			"mms" },
 
 #ifndef NO_ARCHIVE_SUPPORT
 	// Compressed modules
@@ -147,6 +150,7 @@ static const ModCharsetInfo ModCharsetInfos[] =
 	{ MOD_TYPE_OKT , mpt::CharsetISO8859_1  },
 	{ MOD_TYPE_DBM , mpt::CharsetISO8859_1  },
 	{ MOD_TYPE_DIGI, mpt::CharsetISO8859_1  },
+	{ MOD_TYPE_SFX , mpt::CharsetISO8859_1  },
 	// Amiga // DOS
 	{ MOD_TYPE_MOD , mpt::CharsetISO8859_1  },
 	{ MOD_TYPE_MED , mpt::CharsetISO8859_1  },
sfx_r4.patch (15,283 bytes)
Saga Musix

Saga Musix

2016-04-11 01:30

administrator   ~0002325

Just a quick question (I'm finally looking at the patch in more depth)... Did you encounter lots of modules with weird sample names or did you just blindly copy over the invalid chars stuff from the MOD loaders? It's only really needed there because of the lack of magic bytes and because there are actually many Ultimate SoundTracker MODs with weird binary characters in their names, but if this is not the case for SFX modules, it really should not be done there.

Revenant

Revenant

2016-04-13 06:24

reporter   ~0002332

Yeah, that's basically just a leftover from the MOD loader (which this was based directly on, to a degree). Likewise with the STP2 loader I wrote that includes the same function; I don't think it's actually necessary for either of them.

Saga Musix

Saga Musix

2016-04-13 14:39

administrator   ~0002333

Yeah, though so. I refactored the loaders a bit, hopefully I will be able to merge them "soon". :)

Saga Musix

Saga Musix

2016-05-12 14:34

administrator   ~0002365

Patch finally applied in r6354. Yay.

Issue History

Date Modified Username Field Change
2016-01-09 19:41 ncovert New Issue
2016-03-09 03:14 Revenant Note Added: 0002277
2016-03-09 03:14 Revenant File Added: sfx.patch
2016-03-09 03:16 Revenant Note Edited: 0002277 View Revisions
2016-03-09 03:38 Revenant File Added: sfx_r2.patch
2016-03-09 03:38 Revenant Note Edited: 0002277 View Revisions
2016-03-09 20:14 ncovert Note Added: 0002278
2016-03-09 20:15 ncovert Note Edited: 0002278 View Revisions
2016-03-09 20:16 ncovert Note Edited: 0002278 View Revisions
2016-03-10 01:52 Revenant File Added: sfx_r3.patch
2016-03-10 01:58 Revenant Note Added: 0002279
2016-03-10 01:58 Revenant Note Edited: 0002279 View Revisions
2016-03-10 02:29 ncovert Note Added: 0002280
2016-03-10 03:51 Revenant Note Added: 0002281
2016-03-10 03:51 Revenant File Added: sfx_r4.patch
2016-03-10 05:41 manx Assigned To => Saga Musix
2016-03-10 05:41 manx Status new => assigned
2016-03-13 16:30 Saga Musix File Deleted: sfx.patch
2016-03-13 16:30 Saga Musix File Deleted: sfx_r2.patch
2016-03-13 16:30 Saga Musix File Deleted: sfx_r3.patch
2016-04-11 01:30 Saga Musix Note Added: 0002325
2016-04-13 06:24 Revenant Note Added: 0002332
2016-04-13 14:39 Saga Musix Note Added: 0002333
2016-04-24 00:29 Saga Musix Target Version => OpenMPT 1.26.01.00 / libopenmpt 0.2-beta17 (upgrade first)
2016-05-12 14:34 Saga Musix Note Added: 0002365
2016-05-12 14:34 Saga Musix Status assigned => resolved
2016-05-12 14:34 Saga Musix Resolution open => fixed
2016-05-12 14:34 Saga Musix Fixed in Version => OpenMPT 1.26.01.00 / libopenmpt 0.2-beta17 (upgrade first)