diff src/modplug/load_it.cxx @ 2216:3673c7ec4ea2

Sync with schism's modplug engine. Suggested by G¸«ärkan Seng¸«än.
author William Pitcock <nenolod@atheme.org>
date Fri, 07 Dec 2007 12:08:47 -0600
parents 6b5a52635b3b
children 6907fc39b53f
line wrap: on
line diff
--- a/src/modplug/load_it.cxx	Thu Nov 29 04:17:51 2007 +0300
+++ b/src/modplug/load_it.cxx	Fri Dec 07 12:08:47 2007 -0600
@@ -2,15 +2,17 @@
  * This source code is public domain.
  *
  * Authors: Olivier Lapicque <olivierl@jps.net>,
- *          Adam Goode       <adam@evdebs.org> (Endian and char fixes for PPC)
- *          Marco Trillo     <toad@arsystel.com> (Endian fixes for SaveIT, XM->IT Sample Converter)
- *
+ *          Adam Goode       <adam@evdebs.org> (endian and char fixes for PPC)
 */
 
 #include "stdafx.h"
 #include "sndfile.h"
 #include "it_defs.h"
 
+/* blah, -mrsb.
+this is a schism header */
+#include "midi.h"
+
 #ifdef MSC_VER
 #pragma warning(disable:4244)
 #endif
@@ -22,11 +24,8 @@
 { 0, 2, 4, 1, 3, 0, 0, 0 };
 
 //////////////////////////////////////////////////////////
-// Impulse Tracker IT file support
+// Impulse Tracker IT file support (import only)
 
-// for conversion of XM samples
-extern WORD XMPeriodTable[96+8];
-extern UINT XMLinearTable[768];
 
 static inline UINT ConvertVolParam(UINT value)
 //--------------------------------------------
@@ -44,7 +43,7 @@
 		memcpy(penv->name, pis->name, 26);
 		memcpy(penv->filename, pis->filename, 12);
 		penv->nFadeOut = bswapLE16(pis->fadeout) << 6;
-		penv->nGlobalVol = 64;
+		penv->nGlobalVol = 128;
 		for (UINT j=0; j<120; j++)
 		{
 			UINT note = pis->keyboard[j*2];
@@ -56,19 +55,19 @@
 		if (pis->flags & 0x01) penv->dwFlags |= ENV_VOLUME;
 		if (pis->flags & 0x02) penv->dwFlags |= ENV_VOLLOOP;
 		if (pis->flags & 0x04) penv->dwFlags |= ENV_VOLSUSTAIN;
-		penv->nVolLoopStart = pis->vls;
-		penv->nVolLoopEnd = pis->vle;
-		penv->nVolSustainBegin = pis->sls;
-		penv->nVolSustainEnd = pis->sle;
-		penv->nVolEnv = 25;
+		penv->VolEnv.nLoopStart = pis->vls;
+		penv->VolEnv.nLoopEnd = pis->vle;
+		penv->VolEnv.nSustainStart = pis->sls;
+		penv->VolEnv.nSustainEnd = pis->sle;
+		penv->VolEnv.nNodes = 25;
 		for (UINT ev=0; ev<25; ev++)
 		{
-			if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF)
+			if ((penv->VolEnv.Ticks[ev] = pis->nodes[ev*2]) == 0xFF)
 			{
-				penv->nVolEnv = ev;
+				penv->VolEnv.nNodes = ev;
 				break;
 			}
-			penv->VolEnv[ev] = pis->nodes[ev*2+1];
+			penv->VolEnv.Values[ev] = pis->nodes[ev*2+1];
 		}
 		penv->nNNA = pis->nna;
 		penv->nDCT = pis->dnc;
@@ -82,8 +81,8 @@
 		penv->nMidiChannel = pis->mch;
 		penv->wMidiBank = bswapLE16(pis->mbank);
 		penv->nFadeOut = bswapLE16(pis->fadeout) << 5;
-		penv->nGlobalVol = pis->gbv >> 1;
-		if (penv->nGlobalVol > 64) penv->nGlobalVol = 64;
+		penv->nGlobalVol = pis->gbv;
+		if (penv->nGlobalVol > 128) penv->nGlobalVol = 128;
 		for (UINT j=0; j<120; j++)
 		{
 			UINT note = pis->keyboard[j*2];
@@ -97,49 +96,49 @@
 		if (pis->volenv.flags & 2) penv->dwFlags |= ENV_VOLLOOP;
 		if (pis->volenv.flags & 4) penv->dwFlags |= ENV_VOLSUSTAIN;
 		if (pis->volenv.flags & 8) penv->dwFlags |= ENV_VOLCARRY;
-		penv->nVolEnv = pis->volenv.num;
-		if (penv->nVolEnv > 25) penv->nVolEnv = 25;
+		penv->VolEnv.nNodes = pis->volenv.num;
+		if (penv->VolEnv.nNodes > 25) penv->VolEnv.nNodes = 25;
 
-		penv->nVolLoopStart = pis->volenv.lpb;
-		penv->nVolLoopEnd = pis->volenv.lpe;
-		penv->nVolSustainBegin = pis->volenv.slb;
-		penv->nVolSustainEnd = pis->volenv.sle;
+		penv->VolEnv.nLoopStart = pis->volenv.lpb;
+		penv->VolEnv.nLoopEnd = pis->volenv.lpe;
+		penv->VolEnv.nSustainStart = pis->volenv.slb;
+		penv->VolEnv.nSustainEnd = pis->volenv.sle;
 		// Panning Envelope
 		if (pis->panenv.flags & 1) penv->dwFlags |= ENV_PANNING;
 		if (pis->panenv.flags & 2) penv->dwFlags |= ENV_PANLOOP;
 		if (pis->panenv.flags & 4) penv->dwFlags |= ENV_PANSUSTAIN;
 		if (pis->panenv.flags & 8) penv->dwFlags |= ENV_PANCARRY;
-		penv->nPanEnv = pis->panenv.num;
-		if (penv->nPanEnv > 25) penv->nPanEnv = 25;
-		penv->nPanLoopStart = pis->panenv.lpb;
-		penv->nPanLoopEnd = pis->panenv.lpe;
-		penv->nPanSustainBegin = pis->panenv.slb;
-		penv->nPanSustainEnd = pis->panenv.sle;
+		penv->PanEnv.nNodes = pis->panenv.num;
+		if (penv->PanEnv.nNodes > 25) penv->PanEnv.nNodes = 25;
+		penv->PanEnv.nLoopStart = pis->panenv.lpb;
+		penv->PanEnv.nLoopEnd = pis->panenv.lpe;
+		penv->PanEnv.nSustainStart = pis->panenv.slb;
+		penv->PanEnv.nSustainEnd = pis->panenv.sle;
 		// Pitch Envelope
 		if (pis->pitchenv.flags & 1) penv->dwFlags |= ENV_PITCH;
 		if (pis->pitchenv.flags & 2) penv->dwFlags |= ENV_PITCHLOOP;
 		if (pis->pitchenv.flags & 4) penv->dwFlags |= ENV_PITCHSUSTAIN;
 		if (pis->pitchenv.flags & 8) penv->dwFlags |= ENV_PITCHCARRY;
 		if (pis->pitchenv.flags & 0x80) penv->dwFlags |= ENV_FILTER;
-		penv->nPitchEnv = pis->pitchenv.num;
-		if (penv->nPitchEnv > 25) penv->nPitchEnv = 25;
-		penv->nPitchLoopStart = pis->pitchenv.lpb;
-		penv->nPitchLoopEnd = pis->pitchenv.lpe;
-		penv->nPitchSustainBegin = pis->pitchenv.slb;
-		penv->nPitchSustainEnd = pis->pitchenv.sle;
+		penv->PitchEnv.nNodes = pis->pitchenv.num;
+		if (penv->PitchEnv.nNodes > 25) penv->PitchEnv.nNodes = 25;
+		penv->PitchEnv.nLoopStart = pis->pitchenv.lpb;
+		penv->PitchEnv.nLoopEnd = pis->pitchenv.lpe;
+		penv->PitchEnv.nSustainStart = pis->pitchenv.slb;
+		penv->PitchEnv.nSustainEnd = pis->pitchenv.sle;
 		// Envelopes Data
 		for (UINT ev=0; ev<25; ev++)
 		{
-			penv->VolEnv[ev] = pis->volenv.data[ev*3];
-			penv->VolPoints[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]);
-			penv->PanEnv[ev] = pis->panenv.data[ev*3] + 32;
-			penv->PanPoints[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]);
-			penv->PitchEnv[ev] = pis->pitchenv.data[ev*3] + 32;
-			penv->PitchPoints[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]);
+			penv->VolEnv.Values[ev] = pis->volenv.data[ev*3];
+			penv->VolEnv.Ticks[ev] = (pis->volenv.data[ev*3+2] << 8) | (pis->volenv.data[ev*3+1]);
+			penv->PanEnv.Values[ev] = pis->panenv.data[ev*3] + 32;
+			penv->PanEnv.Ticks[ev] = (pis->panenv.data[ev*3+2] << 8) | (pis->panenv.data[ev*3+1]);
+			penv->PitchEnv.Values[ev] = pis->pitchenv.data[ev*3] + 32;
+			penv->PitchEnv.Ticks[ev] = (pis->pitchenv.data[ev*3+2] << 8) | (pis->pitchenv.data[ev*3+1]);
 		}
-		penv->nNNA = pis->nna;
-		penv->nDCT = pis->dct;
-		penv->nDNA = pis->dca;
+		penv->nNNA = pis->nna % 4;
+		penv->nDCT = pis->dct % 4;
+		penv->nDNA = pis->dca % 3;
 		penv->nPPS = pis->pps;
 		penv->nPPC = pis->ppc;
 		penv->nIFC = pis->ifc;
@@ -150,8 +149,8 @@
 		if (penv->nPan > 256) penv->nPan = 128;
 		if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING;
 	}
-	if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
-	if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN;
+	if ((penv->VolEnv.nLoopStart >= 25) || (penv->VolEnv.nLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
+	if ((penv->VolEnv.nSustainStart >= 25) || (penv->VolEnv.nSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN;
 	return TRUE;
 }
 
@@ -167,8 +166,112 @@
 	BYTE chnmask[64], channels_used[64];
 	MODCOMMAND lastvalue[64];
 
+	if ((!lpStream) || (dwMemLength < 0xc2)) return FALSE;
+
 	pifh.id = bswapLE32(pifh.id);
-	pifh.reserved1 = bswapLE16(pifh.reserved1);
+	if (pifh.id == 0x49504D49) {
+		if (dwMemLength < 554) return FALSE;
+
+		WORD tv;
+		INSTRUMENTHEADER *zenv = new INSTRUMENTHEADER;
+		if (!zenv) return FALSE;
+		memset(zenv, 0, sizeof(INSTRUMENTHEADER));
+		memcpy(&tv, lpStream+0x1C, 2); /* trkvers */
+		if (!ITInstrToMPT(lpStream, zenv, tv)) {
+			delete zenv;
+			return FALSE;
+		}
+
+		/* okay, we need samples now */
+		unsigned int q = 554;
+		BYTE expect_samples = lpStream[0x1E];
+
+		m_nType = MOD_TYPE_IT;
+		m_nInstruments = 1;
+		m_nSamples = expect_samples;
+		m_dwSongFlags = SONG_INSTRUMENTMODE | SONG_LINEARSLIDES /* eh? */;
+
+		memcpy(m_szNames[0], lpStream + 0x20, 26);
+		m_szNames[0][26] = 0;
+
+		if (q+(80*expect_samples) >= dwMemLength) {
+			delete zenv;
+			return FALSE;
+		}
+
+		for (UINT nsmp = 0; nsmp < expect_samples; nsmp++) {
+
+			ITSAMPLESTRUCT pis = *(ITSAMPLESTRUCT *)(lpStream+q);
+			q += 80; /* length of ITS header */
+
+			pis.id = bswapLE32(pis.id);
+			pis.length = bswapLE32(pis.length);
+			pis.loopbegin = bswapLE32(pis.loopbegin);
+			pis.loopend = bswapLE32(pis.loopend);
+			pis.C5Speed = bswapLE32(pis.C5Speed);
+			pis.susloopbegin = bswapLE32(pis.susloopbegin);
+			pis.susloopend = bswapLE32(pis.susloopend);
+			pis.samplepointer = bswapLE32(pis.samplepointer);
+	
+			if (pis.id == 0x53504D49)
+			{
+				MODINSTRUMENT *pins = &Ins[nsmp+1];
+				memcpy(pins->name, pis.filename, 12);
+				pins->uFlags = 0;
+				pins->nLength = 0;
+				pins->nLoopStart = pis.loopbegin;
+				pins->nLoopEnd = pis.loopend;
+				pins->nSustainStart = pis.susloopbegin;
+				pins->nSustainEnd = pis.susloopend;
+				pins->nC4Speed = pis.C5Speed;
+				if (!pins->nC4Speed) pins->nC4Speed = 8363;
+				//if (pis.C5Speed < 256) pins->nC4Speed = 256;
+				pins->nVolume = pis.vol << 2;
+				if (pins->nVolume > 256) pins->nVolume = 256;
+				pins->nGlobalVol = pis.gvl;
+				if (pins->nGlobalVol > 64) pins->nGlobalVol = 64;
+				if (pis.flags & 0x10) pins->uFlags |= CHN_LOOP;
+				if (pis.flags & 0x20) pins->uFlags |= CHN_SUSTAINLOOP;
+				if (pis.flags & 0x40) pins->uFlags |= CHN_PINGPONGLOOP;
+				if (pis.flags & 0x80) pins->uFlags |= CHN_PINGPONGSUSTAIN;
+				pins->nPan = (pis.dfp & 0x7F) << 2;
+				if (pins->nPan > 256) pins->nPan = 256;
+				if (pis.dfp & 0x80) pins->uFlags |= CHN_PANNING;
+				pins->nVibType = autovibit2xm[pis.vit & 7];
+				pins->nVibRate = pis.vis;
+				pins->nVibDepth = pis.vid & 0x7F;
+				pins->nVibSweep = pis.vir;
+				if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length))
+				{
+					pins->nLength = pis.length;
+					if (pins->nLength > MAX_SAMPLE_LENGTH) pins->nLength = MAX_SAMPLE_LENGTH;
+					UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U;
+					if (pis.flags & 2)
+					{
+						flags += 5;
+						if (pis.flags & 4) flags |= RSF_STEREO;
+						pins->uFlags |= CHN_16BIT;
+						// IT 2.14 16-bit packed sample ?
+						if (pis.flags & 8) flags = ((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT21516 : RS_IT21416;
+					} else
+					{
+						if (pis.flags & 4) flags |= RSF_STEREO;
+						if (pis.cvt == 0xFF) flags = RS_ADPCM4; else
+						// IT 2.14 8-bit packed sample ?
+						if (pis.flags & 8)	flags =	((pifh.cmwt >= 0x215) && (pis.cvt & 4)) ? RS_IT2158 : RS_IT2148;
+					}
+					ReadSample(&Ins[nsmp+1], flags, (LPSTR)(lpStream+pis.samplepointer), dwMemLength - pis.samplepointer);
+				}
+			}
+			memcpy(m_szNames[nsmp+1], pis.name, 26);
+			
+		}
+
+		Headers[1] = zenv;
+		return TRUE;
+	}
+
+
 	pifh.ordnum = bswapLE16(pifh.ordnum);
 	pifh.insnum = bswapLE16(pifh.insnum);
 	pifh.smpnum = bswapLE16(pifh.smpnum);
@@ -181,29 +284,42 @@
 	pifh.msgoffset = bswapLE32(pifh.msgoffset);
 	pifh.reserved2 = bswapLE32(pifh.reserved2);
 
-	if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
+
+
 	if ((pifh.id != 0x4D504D49) || (pifh.insnum >= MAX_INSTRUMENTS)
-	 || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) return FALSE;
+	 || (pifh.smpnum >= MAX_INSTRUMENTS)) return FALSE;
 	if (dwMemPos + pifh.ordnum + pifh.insnum*4
 	 + pifh.smpnum*4 + pifh.patnum*4 > dwMemLength) return FALSE;
 	m_nType = MOD_TYPE_IT;
+	if (!(pifh.flags & 0x01)) m_dwSongFlags |= SONG_NOSTEREO;
+	if (pifh.flags & 0x04) m_dwSongFlags |= SONG_INSTRUMENTMODE;
 	if (pifh.flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES;
 	if (pifh.flags & 0x10) m_dwSongFlags |= SONG_ITOLDEFFECTS;
 	if (pifh.flags & 0x20) m_dwSongFlags |= SONG_ITCOMPATMODE;
+	if (pifh.flags & 0x40) {
+		midi_flags |= MIDI_PITCH_BEND;
+		midi_pitch_depth = pifh.pwd;
+	}
 	if (pifh.flags & 0x80) m_dwSongFlags |= SONG_EMBEDMIDICFG;
 	if (pifh.flags & 0x1000) m_dwSongFlags |= SONG_EXFILTERRANGE;
 	memcpy(m_szNames[0], pifh.songname, 26);
 	m_szNames[0][26] = 0;
+	if (pifh.cwtv >= 0x0213) {
+		m_rowHighlightMinor = pifh.hilight_minor;
+		m_rowHighlightMajor = pifh.hilight_major;
+	} else {
+		m_rowHighlightMinor = 4;
+		m_rowHighlightMajor = 16;
+	}
 	// Global Volume
-	if (pifh.globalvol)
-	{
-		m_nDefaultGlobalVolume = pifh.globalvol << 1;
-		if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256;
-		if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
-	}
+        m_nDefaultGlobalVolume = pifh.globalvol << 1;
+        if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
 	if (pifh.speed) m_nDefaultSpeed = pifh.speed;
 	if (pifh.tempo) m_nDefaultTempo = pifh.tempo;
-	m_nSongPreAmp = pifh.mv & 0x7F;
+	m_nSongPreAmp = pifh.mv;
+        if (m_nSongPreAmp > 128)
+                m_nSongPreAmp = 128;
+	m_nStereoSeparation = pifh.sep;
 	// Reading Channels Pan Positions
 	for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF)
 	{
@@ -229,6 +345,7 @@
 	UINT nordsize = pifh.ordnum;
 	if (nordsize > MAX_ORDERS) nordsize = MAX_ORDERS;
 	memcpy(Order, lpStream+dwMemPos, nordsize);
+
 	dwMemPos += pifh.ordnum;
 	// Reading Instrument Offsets
 	memset(inspos, 0, sizeof(inspos));
@@ -263,6 +380,17 @@
 	       patpos[j] = bswapLE32(patpos[j]);
 	}
 	dwMemPos += pifh.patnum * 4;
+
+	for (UINT i = 0; i < pifh.ordnum; i++) {
+		if (Order[i] >= pifh.patnum && Order[i] < MAX_PATTERNS) {
+			pifh.patnum = Order[i];
+			for (UINT j = patpossize; j < (unsigned)(pifh.patnum>>2); j++)
+				patpos[j] = 0;
+			patpossize = pifh.patnum;
+		}
+	}
+
+
 	// Reading IT Extra Info
 	if (dwMemPos + 2 < dwMemLength)
 	{
@@ -277,8 +405,13 @@
 		{
 			memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG));
 			dwMemPos += sizeof(MODMIDICFG);
+		} else {
+			ResetMidiCfg();
 		}
+	} else {
+		ResetMidiCfg();
 	}
+#if 0
 	// Read pattern names: "PNAM"
 	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
 	{
@@ -295,8 +428,10 @@
 			dwMemPos += len;
 		}
 	}
+#endif
 	// 4-channels minimum
 	m_nChannels = 4;
+#if 0
 	// Read channel names: "CNAM"
 	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
 	{
@@ -319,6 +454,7 @@
 	{
 		dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
 	}
+#endif
 	// Checking for unused channels
 	UINT npatterns = pifh.patnum;
 	if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
@@ -366,8 +502,7 @@
 		}
 	}
 	// Reading Instruments
-	m_nInstruments = 0;
-	if (pifh.flags & 0x04) m_nInstruments = pifh.insnum;
+	m_nInstruments = pifh.insnum;
 	if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1;
 	for (UINT nins=0; nins<m_nInstruments; nins++)
 	{
@@ -407,7 +542,7 @@
 			pins->nSustainEnd = pis.susloopend;
 			pins->nC4Speed = pis.C5Speed;
 			if (!pins->nC4Speed) pins->nC4Speed = 8363;
-			if (pis.C5Speed < 256) pins->nC4Speed = 256;
+			//if (pis.C5Speed < 256) pins->nC4Speed = 256;
 			pins->nVolume = pis.vol << 2;
 			if (pins->nVolume > 256) pins->nVolume = 256;
 			pins->nGlobalVol = pis.gvl;
@@ -422,7 +557,7 @@
 			pins->nVibType = autovibit2xm[pis.vit & 7];
 			pins->nVibRate = pis.vis;
 			pins->nVibDepth = pis.vid & 0x7F;
-			pins->nVibSweep = (pis.vir + 3) / 4;
+			pins->nVibSweep = pis.vir;
 			if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length))
 			{
 				pins->nLength = pis.length;
@@ -453,6 +588,7 @@
 		if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength))
 		{
 			PatternSize[npat] = 64;
+			PatternAllocSize[npat] = 64;
 			Patterns[npat] = AllocatePattern(64, m_nChannels);
 			continue;
 		}
@@ -462,6 +598,7 @@
 		if ((rows < 4) || (rows > 256)) continue;
 		if (patpos[npat]+8+len > dwMemLength) continue;
 		PatternSize[npat] = rows;
+		PatternAllocSize[npat] = rows;
 		if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) continue;
 		memset(lastvalue, 0, sizeof(lastvalue));
 		memset(chnmask, 0, sizeof(chnmask));
@@ -551,7 +688,7 @@
 					// 193-202: Portamento To
 					if ((vol >= 193) && (vol <= 202)) { m[ch].volcmd = VOLCMD_TONEPORTAMENTO; m[ch].vol = vol - 193; } else
 					// 203-212: Vibrato
-					if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; }
+					if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATO; m[ch].vol = vol - 203; }
 					lastvalue[ch].volcmd = m[ch].volcmd;
 					lastvalue[ch].vol = m[ch].vol;
 				}
@@ -592,14 +729,18 @@
 
 #ifndef MODPLUG_NO_FILESAVE
 //#define SAVEITTIMESTAMP
+
+#ifdef MSC_VER
 #pragma warning(disable:4100)
+#endif
 
+#if 0
 BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking)
 //---------------------------------------------------------
 {
 	DWORD dwPatNamLen, dwChnNamLen;
-	ITFILEHEADER header, writeheader;
-	ITINSTRUMENT iti, writeiti;
+	ITFILEHEADER header;
+	ITINSTRUMENT iti;
 	ITSAMPLESTRUCT itss;
 	BYTE smpcount[MAX_SAMPLES];
 	DWORD inspos[MAX_INSTRUMENTS];
@@ -621,9 +762,10 @@
 	memset(&header, 0, sizeof(header));
 	dwPatNamLen = 0;
 	dwChnNamLen = 0;
-	header.id = 0x4D504D49; // IMPM
-	lstrcpyn((char *)header.songname, m_szNames[0], 27);
-	header.reserved1 = 0x1004;
+	header.id = 0x4D504D49;
+	lstrcpyn(header.songname, m_szNames[0], 27);
+	header.hilight_minor = m_rowHighlightMinor;
+	header.hilight_major = m_rowHighlightMajor;
 	header.ordnum = 0;
 	while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++;
 	if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF;
@@ -635,16 +777,13 @@
 	header.cmwt = 0x200;
 	header.flags = 0x0001;
 	header.special = 0x0006;
-	if (m_nInstruments) header.flags |= 0x04;
+	if (m_dwSongFlags & SONG_INSTRUMENTMODE) header.flags |= 0x04;
 	if (m_dwSongFlags & SONG_LINEARSLIDES) header.flags |= 0x08;
 	if (m_dwSongFlags & SONG_ITOLDEFFECTS) header.flags |= 0x10;
 	if (m_dwSongFlags & SONG_ITCOMPATMODE) header.flags |= 0x20;
 	if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
 	header.globalvol = m_nDefaultGlobalVolume >> 1;
 	header.mv = m_nSongPreAmp;
-	// clip song pre-amp values (between 0x20 and 0x7f)
-	if (header.mv < 0x20) header.mv = 0x20;
-	if (header.mv > 0x7F) header.mv = 0x7F;
 	header.speed = m_nDefaultSpeed;
 	header.tempo = m_nDefaultTempo;
 	header.sep = m_nStereoSeparation;
@@ -691,25 +830,7 @@
 		header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4;
 	}
 	// Write file header
-	memcpy(writeheader, header, sizeof(header));
-
-	// Byteswap header information
-	writeheader.id = bswapLE32(writeheader.id);
-	writeheader.reserved1 = bswapLE16(writeheader.reserved1);
-	writeheader.ordnum = bswapLE16(writeheader.ordnum);
-	writeheader.insnum = bswapLE16(writeheader.insnum);
-	writeheader.smpnum = bswapLE16(writeheader.smpnum);
-	writeheader.patnum = bswapLE16(writeheader.patnum);
-	writeheader.cwtv = bswapLE16(writeheader.cwtv);
-	writeheader.cmwt = bswapLE16(writeheader.cmwt);
-	writeheader.flags = bswapLE16(writeheader.flags);
-	writeheader.special = bswapLE16(writeheader.special);
-	writeheader.msglength = bswapLE16(writeheader.msglength);
-	writeheader.msgoffset = bswapLE32(writeheader.msgoffset);
-	writeheader.reserved2 = bswapLE32(writeheader.reserved2);
-
-	fwrite(&writeheader, 1, sizeof(writeheader), f);
-
+	fwrite(&header, 1, sizeof(header), f);
 	fwrite(Order, 1, header.ordnum, f);
 	if (header.insnum) fwrite(inspos, 4, header.insnum, f);
 	if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
@@ -740,19 +861,17 @@
 	// Writing pattern names
 	if (dwPatNamLen)
 	{
-		DWORD d = bswapLE32(0x4d414e50);
-		UINT len= bswapLE32(dwPatNamLen);
+		DWORD d = 0x4d414e50;
 		fwrite(&d, 1, 4, f);
-		write(&len, 1, 4, f);
+		fwrite(&dwPatNamLen, 1, 4, f);
 		fwrite(m_lpszPatternNames, 1, dwPatNamLen, f);
 	}
 	// Writing channel Names
 	if (dwChnNamLen)
 	{
-		DWORD d = bswapLE32(0x4d414e43);
-		UINT len= bswapLE32(dwChnNamLen);
+		DWORD d = 0x4d414e43;
 		fwrite(&d, 1, 4, f);
-		fwrite(&len, 1, 4, f);
+		fwrite(&dwChnNamLen, 1, 4, f);
 		UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME;
 		for (UINT inam=0; inam<nChnNames; inam++)
 		{
@@ -789,7 +908,7 @@
 			iti.fadeout = penv->nFadeOut >> 5;
 			iti.pps = penv->nPPS;
 			iti.ppc = penv->nPPC;
-			iti.gbv = (BYTE)(penv->nGlobalVol << 1);
+			iti.gbv = (BYTE)penv->nGlobalVol;
 			iti.dfp = (BYTE)penv->nPan >> 2;
 			if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80;
 			iti.rv = penv->nVolSwing;
@@ -813,44 +932,44 @@
 			if (penv->dwFlags & ENV_VOLLOOP) iti.volenv.flags |= 0x02;
 			if (penv->dwFlags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04;
 			if (penv->dwFlags & ENV_VOLCARRY) iti.volenv.flags |= 0x08;
-			iti.volenv.num = (BYTE)penv->nVolEnv;
-			iti.volenv.lpb = (BYTE)penv->nVolLoopStart;
-			iti.volenv.lpe = (BYTE)penv->nVolLoopEnd;
-			iti.volenv.slb = penv->nVolSustainBegin;
-			iti.volenv.sle = penv->nVolSustainEnd;
+			iti.volenv.num = (BYTE)penv->VolEnv.nNodes;
+			iti.volenv.lpb = (BYTE)penv->VolEnv.nLoopStart;
+			iti.volenv.lpe = (BYTE)penv->VolEnv.nLoopEnd;
+			iti.volenv.slb = penv->VolEnv.nSustainStart;
+			iti.volenv.sle = penv->VolEnv.nSustainEnd;
 			// Writing Panning envelope
 			if (penv->dwFlags & ENV_PANNING) iti.panenv.flags |= 0x01;
 			if (penv->dwFlags & ENV_PANLOOP) iti.panenv.flags |= 0x02;
 			if (penv->dwFlags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04;
 			if (penv->dwFlags & ENV_PANCARRY) iti.panenv.flags |= 0x08;
-			iti.panenv.num = (BYTE)penv->nPanEnv;
-			iti.panenv.lpb = (BYTE)penv->nPanLoopStart;
-			iti.panenv.lpe = (BYTE)penv->nPanLoopEnd;
-			iti.panenv.slb = penv->nPanSustainBegin;
-			iti.panenv.sle = penv->nPanSustainEnd;
+			iti.panenv.num = (BYTE)penv->PanEnv.nNodes;
+			iti.panenv.lpb = (BYTE)penv->PanEnv.nLoopStart;
+			iti.panenv.lpe = (BYTE)penv->PanEnv.nLoopEnd;
+			iti.panenv.slb = penv->PanEnv.nSustainStart;
+			iti.panenv.sle = penv->PanEnv.nSustainEnd;
 			// Writing Pitch Envelope
 			if (penv->dwFlags & ENV_PITCH) iti.pitchenv.flags |= 0x01;
 			if (penv->dwFlags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02;
 			if (penv->dwFlags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04;
 			if (penv->dwFlags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08;
 			if (penv->dwFlags & ENV_FILTER) iti.pitchenv.flags |= 0x80;
-			iti.pitchenv.num = (BYTE)penv->nPitchEnv;
-			iti.pitchenv.lpb = (BYTE)penv->nPitchLoopStart;
-			iti.pitchenv.lpe = (BYTE)penv->nPitchLoopEnd;
-			iti.pitchenv.slb = (BYTE)penv->nPitchSustainBegin;
-			iti.pitchenv.sle = (BYTE)penv->nPitchSustainEnd;
+			iti.pitchenv.num = (BYTE)penv->PitchEnv.nNodes;
+			iti.pitchenv.lpb = (BYTE)penv->PitchEnv.nLoopStart;
+			iti.pitchenv.lpe = (BYTE)penv->PitchEnv.nLoopEnd;
+			iti.pitchenv.slb = (BYTE)penv->PitchEnv.nSustainStart;
+			iti.pitchenv.sle = (BYTE)penv->PitchEnv.nSustainEnd;
 			// Writing Envelopes data
 			for (UINT ev=0; ev<25; ev++)
 			{
-				iti.volenv.data[ev*3] = penv->VolEnv[ev];
-				iti.volenv.data[ev*3+1] = penv->VolPoints[ev] & 0xFF;
-				iti.volenv.data[ev*3+2] = penv->VolPoints[ev] >> 8;
-				iti.panenv.data[ev*3] = penv->PanEnv[ev] - 32;
-				iti.panenv.data[ev*3+1] = penv->PanPoints[ev] & 0xFF;
-				iti.panenv.data[ev*3+2] = penv->PanPoints[ev] >> 8;
-				iti.pitchenv.data[ev*3] = penv->PitchEnv[ev] - 32;
-				iti.pitchenv.data[ev*3+1] = penv->PitchPoints[ev] & 0xFF;
-				iti.pitchenv.data[ev*3+2] = penv->PitchPoints[ev] >> 8;
+				iti.volenv.data[ev*3] = penv->VolEnv.Values[ev];
+				iti.volenv.data[ev*3+1] = penv->VolEnv.Ticks[ev] & 0xFF;
+				iti.volenv.data[ev*3+2] = penv->VolEnv.Ticks[ev] >> 8;
+				iti.panenv.data[ev*3] = penv->PanEnv.Values[ev] - 32;
+				iti.panenv.data[ev*3+1] = penv->PanEnv.Ticks[ev] & 0xFF;
+				iti.panenv.data[ev*3+2] = penv->PanEnv.Ticks[ev] >> 8;
+				iti.pitchenv.data[ev*3] = penv->PitchEnv.Values[ev] - 32;
+				iti.pitchenv.data[ev*3+1] = penv->PitchEnv.Ticks[ev] & 0xFF;
+				iti.pitchenv.data[ev*3+2] = penv->PitchEnv.Ticks[ev] >> 8;
 			}
 		} else
 		// Save Empty Instrument
@@ -865,15 +984,7 @@
 		// Writing instrument
 		inspos[nins-1] = dwPos;
 		dwPos += sizeof(ITINSTRUMENT);
-
-		memcpy(&writeiti, &iti, sizeof(ITINSTRUMENT));
-
-		writeiti.fadeout = bswapLE16(writeiti.fadeout);
-		writeiti.id = bswapLE32(writeiti.id);
-		writeiti.trkvers = bswapLE16(writeiti.trkvers);
-		writeiti.mbank = bswapLE16(writeiti.mbank);
-
-		fwrite(&writeiti, 1, sizeof(ITINSTRUMENT), f);
+		fwrite(&iti, 1, sizeof(ITINSTRUMENT), f);
 	}
 	// Writing sample headers
 	memset(&itss, 0, sizeof(itss));
@@ -891,7 +1002,7 @@
 		if (!Patterns[npat]) continue;
 		patpos[npat] = dwPos;
 		patinfo[0] = 0;
-		patinfo[1] = bswapLE16(PatternSize[npat]);
+		patinfo[1] = PatternSize[npat];
 		patinfo[2] = 0;
 		patinfo[3] = 0;
 		// Check for empty pattern
@@ -899,7 +1010,8 @@
 		{
 			MODCOMMAND *pzc = Patterns[npat];
 			UINT nz = PatternSize[npat] * m_nChannels;
-			for (UINT iz=0; iz<nz; iz++)
+                        UINT iz;
+			for (iz=0; iz<nz; iz++)
 			{
 				if ((pzc[iz].note) || (pzc[iz].instr)
 				 || (pzc[iz].volcmd) || (pzc[iz].command)) break;
@@ -926,7 +1038,7 @@
 				UINT vol = 0xFF;
 				UINT note = m->note;
 				if (note) b |= 1;
-				if ((note) && (note < 0x80)) note--; // 0xfe->0x80 --Toad
+				if ((note) && (note < 0x80)) note--;
 				if (m->instr) b |= 2;
 				if (m->volcmd)
 				{
@@ -939,8 +1051,8 @@
 					case VOLCMD_VOLSLIDEDOWN:	vol = 95 + ConvertVolParam(m->vol); break;
 					case VOLCMD_FINEVOLUP:		vol = 65 + ConvertVolParam(m->vol); break;
 					case VOLCMD_FINEVOLDOWN:	vol = 75 + ConvertVolParam(m->vol); break;
-					case VOLCMD_VIBRATOSPEED:	vol = 203 + ConvertVolParam(m->vol); break;
-					case VOLCMD_VIBRATO:		vol = 203; break;
+					case VOLCMD_VIBRATOSPEED:	vol = 203; break;
+					case VOLCMD_VIBRATO:		vol = 203 + ConvertVolParam(m->vol); break;
 					case VOLCMD_TONEPORTAMENTO:	vol = 193 + ConvertVolParam(m->vol); break;
 					case VOLCMD_PORTADOWN:		vol = 105 + ConvertVolParam(m->vol); break;
 					case VOLCMD_PORTAUP:		vol = 115 + ConvertVolParam(m->vol); break;
@@ -1034,7 +1146,6 @@
 			fwrite(buf, 1, len, f);
 		}
 		fseek(f, dwPatPos, SEEK_SET);
-		patinfo[0] = bswapLE16(patinfo[0]); // byteswap -- Toad
 		fwrite(patinfo, 8, 1, f);
 		fseek(f, dwPos, SEEK_SET);
 	}
@@ -1047,7 +1158,7 @@
 		memcpy(itss.name, m_szNames[nsmp], 26);
 		itss.id = 0x53504D49;
 		itss.gvl = (BYTE)psmp->nGlobalVol;
-		if (m_nInstruments)
+		if (m_dwSongFlags & SONG_INSTRUMENTMODE)
 		{
 			for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu])
 			{
@@ -1067,25 +1178,7 @@
 		if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40;
 		if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80;
 		itss.C5Speed = psmp->nC4Speed;
-		if (!itss.C5Speed) // if no C5Speed assume it is XM Sample
-		{ 
-			UINT period;
-
-			/**
-			 * C5 note => number 61, but in XM samples:
-			 * RealNote = Note + RelativeTone
-			 */
-			period = GetPeriodFromNote(61+psmp->RelativeTone, psmp->nFineTune, 0);
-						
-			if (period)
-				itss.C5Speed = GetFreqFromPeriod(period, 0, 0);
-			/**
-			 * If it didn`t work, it may not be a XM file;
-			 * so put the default C5Speed, 8363Hz.
-			 */
-	 		if (!itss.C5Speed) itss.C5Speed = 8363;
-		}
-
+		if (!itss.C5Speed) itss.C5Speed = 8363;
 		itss.length = psmp->nLength;
 		itss.loopbegin = psmp->nLoopStart;
 		itss.loopend = psmp->nLoopEnd;
@@ -1096,7 +1189,7 @@
 		itss.vit = autovibxm2it[psmp->nVibType & 7];
 		itss.vis = psmp->nVibRate;
 		itss.vid = psmp->nVibDepth;
-		itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255;
+		itss.vir = psmp->nVibSweep;
 		if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80;
 		if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01;
 		UINT flags = RS_PCM8S;
@@ -1104,7 +1197,7 @@
 		if (nPacking)
 		{
 			if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO)))
-			 && (CanPackSample((char *)psmp->pSample, psmp->nLength, nPacking)))
+			 && (CanPackSample(psmp->pSample, psmp->nLength, nPacking)))
 			{
 				flags = RS_ADPCM4;
 				itss.cvt = 0xFF;
@@ -1125,16 +1218,6 @@
 		}
 		itss.samplepointer = dwPos;
 		fseek(f, smppos[nsmp-1], SEEK_SET);
-
-		itss.id = bswapLE32(itss.id);
-		itss.length = bswapLE32(itss.length);
-		itss.loopbegin = bswapLE32(itss.loopbegin);
-		itss.loopend = bswapLE32(itss.loopend);
-		itss.C5Speed = bswapLE32(itss.C5Speed);
-		itss.susloopbegin = bswapLE32(itss.susloopbegin);
-		itss.susloopend = bswapLE32(itss.susloopend);
-		itss.samplepointer = bswapLE32(itss.samplepointer);
-
 		fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
 		fseek(f, dwPos, SEEK_SET);
 		if ((psmp->pSample) && (psmp->nLength))
@@ -1144,33 +1227,18 @@
 	}
 	// Updating offsets
 	fseek(f, dwHdrPos, SEEK_SET);
-	
-	/* <Toad> Now we can byteswap them ;-) */
-	UINT WW;
-	UINT WX;
-	WX = (UINT)header.insnum;
-	WX <<= 2;
-	for (WW=0; WW < (WX>>2); WW++)
-	       inspos[WW] = bswapLE32(inspos[WW]);
-
-	WX = (UINT)header.smpnum;
-	WX <<= 2;
-	for (WW=0; WW < (WX>>2); WW++)
-	       smppos[WW] = bswapLE32(smppos[WW]);
-
-	WX=(UINT)header.patnum;
-	WX <<= 2;
-	for (WW=0; WW < (WX>>2); WW++)
-	       patpos[WW] = bswapLE32(patpos[WW]);
-	
 	if (header.insnum) fwrite(inspos, 4, header.insnum, f);
 	if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
 	if (header.patnum) fwrite(patpos, 4, header.patnum, f);
 	fclose(f);
 	return TRUE;
 }
+#endif
 
-//#pragma warning(default:4100)
+#ifdef MSC_VER
+#pragma warning(default:4100)
+#endif
+
 #endif // MODPLUG_NO_FILESAVE
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1374,8 +1442,7 @@
 {
 	DWORD chinfo[64];
 	CHAR s[32];
-	DWORD nPluginSize, writeSwapDWORD;
-	SNDMIXPLUGININFO writePluginInfo;
+	DWORD nPluginSize;
 	UINT nTotalSize = 0;
 	UINT nChInfo = 0;
 
@@ -1400,23 +1467,9 @@
 				s[2] = '0' + (i/10);
 				s[3] = '0' + (i%10);
 				fwrite(s, 1, 4, f);
-				writeSwapDWORD = bswapLE32(nPluginSize);
-				fwrite(&writeSwapDWORD, 1, 4, f);
-
-				// Copy Information To Be Written for ByteSwapping
-				memcpy(&writePluginInfo, &p->Info, sizeof(SNDMIXPLUGININFO));
-				writePluginInfo.dwPluginId1 = bswapLE32(p->Info.dwPluginId1);
-				writePluginInfo.dwPluginId2 = bswapLE32(p->Info.dwPluginId2);
-				writePluginInfo.dwInputRouting = bswapLE32(p->Info.dwInputRouting);
-				writePluginInfo.dwOutputRouting = bswapLE32(p->Info.dwOutputRouting);
-				for (UINT j=0; j<4; j++)
-				{
-				        writePluginInfo.dwReserved[j] = bswapLE32(p->Info.dwReserved[j]);
-				}
-
-				fwrite(&writePluginInfo, 1, sizeof(SNDMIXPLUGININFO), f);
-				writeSwapDWORD = bswapLE32(m_MixPlugins[i].nPluginDataSize);
-				fwrite(&writeSwapDWORD, 1, 4, f);
+				fwrite(&nPluginSize, 1, 4, f);
+				fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f);
+				fwrite(&m_MixPlugins[i].nPluginDataSize, 1, 4, f);
 				if (m_MixPlugins[i].pPluginData)
 				{
 					fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f);
@@ -1432,7 +1485,6 @@
 			if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0)
 			{
 				nChInfo = j+1;
-				chinfo[j] = bswapLE32(chinfo[j]); // inplace BS
 			}
 		}
 	}
@@ -1440,11 +1492,10 @@
 	{
 		if (f)
 		{
-			nPluginSize = bswapLE32(0x58464843);
+			nPluginSize = 0x58464843;
 			fwrite(&nPluginSize, 1, 4, f);
 			nPluginSize = nChInfo*4;
-			writeSwapDWORD = bswapLE32(nPluginSize);
-			fwrite(&writeSwapDWORD, 1, 4, f);
+			fwrite(&nPluginSize, 1, 4, f);
 			fwrite(chinfo, 1, nPluginSize, f);
 		}
 		nTotalSize += nChInfo*4 + 8;