diff src/modplug/load_it.cxx @ 2218:6907fc39b53f

That didn't merge properly. I'll try again at some other point.
author William Pitcock <nenolod@atheme.org>
date Fri, 07 Dec 2007 12:13:37 -0600
parents 3673c7ec4ea2
children 107c1fed3d92
line wrap: on
line diff
--- a/src/modplug/load_it.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_it.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -2,17 +2,15 @@
  * This source code is public domain.
  *
  * Authors: Olivier Lapicque <olivierl@jps.net>,
- *          Adam Goode       <adam@evdebs.org> (endian and char fixes for PPC)
+ *          Adam Goode       <adam@evdebs.org> (Endian and char fixes for PPC)
+ *          Marco Trillo     <toad@arsystel.com> (Endian fixes for SaveIT, XM->IT Sample Converter)
+ *
 */
 
 #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
@@ -24,8 +22,11 @@
 { 0, 2, 4, 1, 3, 0, 0, 0 };
 
 //////////////////////////////////////////////////////////
-// Impulse Tracker IT file support (import only)
+// Impulse Tracker IT file support
 
+// for conversion of XM samples
+extern WORD XMPeriodTable[96+8];
+extern UINT XMLinearTable[768];
 
 static inline UINT ConvertVolParam(UINT value)
 //--------------------------------------------
@@ -43,7 +44,7 @@
 		memcpy(penv->name, pis->name, 26);
 		memcpy(penv->filename, pis->filename, 12);
 		penv->nFadeOut = bswapLE16(pis->fadeout) << 6;
-		penv->nGlobalVol = 128;
+		penv->nGlobalVol = 64;
 		for (UINT j=0; j<120; j++)
 		{
 			UINT note = pis->keyboard[j*2];
@@ -55,19 +56,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->VolEnv.nLoopStart = pis->vls;
-		penv->VolEnv.nLoopEnd = pis->vle;
-		penv->VolEnv.nSustainStart = pis->sls;
-		penv->VolEnv.nSustainEnd = pis->sle;
-		penv->VolEnv.nNodes = 25;
+		penv->nVolLoopStart = pis->vls;
+		penv->nVolLoopEnd = pis->vle;
+		penv->nVolSustainBegin = pis->sls;
+		penv->nVolSustainEnd = pis->sle;
+		penv->nVolEnv = 25;
 		for (UINT ev=0; ev<25; ev++)
 		{
-			if ((penv->VolEnv.Ticks[ev] = pis->nodes[ev*2]) == 0xFF)
+			if ((penv->VolPoints[ev] = pis->nodes[ev*2]) == 0xFF)
 			{
-				penv->VolEnv.nNodes = ev;
+				penv->nVolEnv = ev;
 				break;
 			}
-			penv->VolEnv.Values[ev] = pis->nodes[ev*2+1];
+			penv->VolEnv[ev] = pis->nodes[ev*2+1];
 		}
 		penv->nNNA = pis->nna;
 		penv->nDCT = pis->dnc;
@@ -81,8 +82,8 @@
 		penv->nMidiChannel = pis->mch;
 		penv->wMidiBank = bswapLE16(pis->mbank);
 		penv->nFadeOut = bswapLE16(pis->fadeout) << 5;
-		penv->nGlobalVol = pis->gbv;
-		if (penv->nGlobalVol > 128) penv->nGlobalVol = 128;
+		penv->nGlobalVol = pis->gbv >> 1;
+		if (penv->nGlobalVol > 64) penv->nGlobalVol = 64;
 		for (UINT j=0; j<120; j++)
 		{
 			UINT note = pis->keyboard[j*2];
@@ -96,49 +97,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->VolEnv.nNodes = pis->volenv.num;
-		if (penv->VolEnv.nNodes > 25) penv->VolEnv.nNodes = 25;
+		penv->nVolEnv = pis->volenv.num;
+		if (penv->nVolEnv > 25) penv->nVolEnv = 25;
 
-		penv->VolEnv.nLoopStart = pis->volenv.lpb;
-		penv->VolEnv.nLoopEnd = pis->volenv.lpe;
-		penv->VolEnv.nSustainStart = pis->volenv.slb;
-		penv->VolEnv.nSustainEnd = pis->volenv.sle;
+		penv->nVolLoopStart = pis->volenv.lpb;
+		penv->nVolLoopEnd = pis->volenv.lpe;
+		penv->nVolSustainBegin = pis->volenv.slb;
+		penv->nVolSustainEnd = 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->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;
+		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;
 		// 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->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;
+		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;
 		// Envelopes Data
 		for (UINT ev=0; ev<25; ev++)
 		{
-			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->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->nNNA = pis->nna % 4;
-		penv->nDCT = pis->dct % 4;
-		penv->nDNA = pis->dca % 3;
+		penv->nNNA = pis->nna;
+		penv->nDCT = pis->dct;
+		penv->nDNA = pis->dca;
 		penv->nPPS = pis->pps;
 		penv->nPPC = pis->ppc;
 		penv->nIFC = pis->ifc;
@@ -149,8 +150,8 @@
 		if (penv->nPan > 256) penv->nPan = 128;
 		if (pis->dfp < 0x80) penv->dwFlags |= ENV_SETPANNING;
 	}
-	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;
+	if ((penv->nVolLoopStart >= 25) || (penv->nVolLoopEnd >= 25)) penv->dwFlags &= ~ENV_VOLLOOP;
+	if ((penv->nVolSustainBegin >= 25) || (penv->nVolSustainEnd >= 25)) penv->dwFlags &= ~ENV_VOLSUSTAIN;
 	return TRUE;
 }
 
@@ -166,112 +167,8 @@
 	BYTE chnmask[64], channels_used[64];
 	MODCOMMAND lastvalue[64];
 
-	if ((!lpStream) || (dwMemLength < 0xc2)) return FALSE;
-
 	pifh.id = bswapLE32(pifh.id);
-	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.reserved1 = bswapLE16(pifh.reserved1);
 	pifh.ordnum = bswapLE16(pifh.ordnum);
 	pifh.insnum = bswapLE16(pifh.insnum);
 	pifh.smpnum = bswapLE16(pifh.smpnum);
@@ -284,42 +181,29 @@
 	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 >= MAX_INSTRUMENTS)) return FALSE;
+	 || (!pifh.smpnum) || (pifh.smpnum >= MAX_INSTRUMENTS) || (!pifh.ordnum)) 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;
 	}
-	// Global Volume
-        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;
-        if (m_nSongPreAmp > 128)
-                m_nSongPreAmp = 128;
-	m_nStereoSeparation = pifh.sep;
+	m_nSongPreAmp = pifh.mv & 0x7F;
 	// Reading Channels Pan Positions
 	for (int ipan=0; ipan<64; ipan++) if (pifh.chnpan[ipan] != 0xFF)
 	{
@@ -345,7 +229,6 @@
 	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));
@@ -380,17 +263,6 @@
 	       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)
 	{
@@ -405,13 +277,8 @@
 		{
 			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))
 	{
@@ -428,10 +295,8 @@
 			dwMemPos += len;
 		}
 	}
-#endif
 	// 4-channels minimum
 	m_nChannels = 4;
-#if 0
 	// Read channel names: "CNAM"
 	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
 	{
@@ -454,7 +319,6 @@
 	{
 		dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
 	}
-#endif
 	// Checking for unused channels
 	UINT npatterns = pifh.patnum;
 	if (npatterns > MAX_PATTERNS) npatterns = MAX_PATTERNS;
@@ -502,7 +366,8 @@
 		}
 	}
 	// Reading Instruments
-	m_nInstruments = pifh.insnum;
+	m_nInstruments = 0;
+	if (pifh.flags & 0x04) m_nInstruments = pifh.insnum;
 	if (m_nInstruments >= MAX_INSTRUMENTS) m_nInstruments = MAX_INSTRUMENTS-1;
 	for (UINT nins=0; nins<m_nInstruments; nins++)
 	{
@@ -542,7 +407,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;
@@ -557,7 +422,7 @@
 			pins->nVibType = autovibit2xm[pis.vit & 7];
 			pins->nVibRate = pis.vis;
 			pins->nVibDepth = pis.vid & 0x7F;
-			pins->nVibSweep = pis.vir;
+			pins->nVibSweep = (pis.vir + 3) / 4;
 			if ((pis.samplepointer) && (pis.samplepointer < dwMemLength) && (pis.length))
 			{
 				pins->nLength = pis.length;
@@ -588,7 +453,6 @@
 		if ((!patpos[npat]) || ((DWORD)patpos[npat] + 4 >= dwMemLength))
 		{
 			PatternSize[npat] = 64;
-			PatternAllocSize[npat] = 64;
 			Patterns[npat] = AllocatePattern(64, m_nChannels);
 			continue;
 		}
@@ -598,7 +462,6 @@
 		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));
@@ -688,7 +551,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_VIBRATO; m[ch].vol = vol - 203; }
+					if ((vol >= 203) && (vol <= 212)) { m[ch].volcmd = VOLCMD_VIBRATOSPEED; m[ch].vol = vol - 203; }
 					lastvalue[ch].volcmd = m[ch].volcmd;
 					lastvalue[ch].vol = m[ch].vol;
 				}
@@ -729,18 +592,14 @@
 
 #ifndef MODPLUG_NO_FILESAVE
 //#define SAVEITTIMESTAMP
+#pragma warning(disable:4100)
 
-#ifdef MSC_VER
-#pragma warning(disable:4100)
-#endif
-
-#if 0
 BOOL CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking)
 //---------------------------------------------------------
 {
 	DWORD dwPatNamLen, dwChnNamLen;
-	ITFILEHEADER header;
-	ITINSTRUMENT iti;
+	ITFILEHEADER header, writeheader;
+	ITINSTRUMENT iti, writeiti;
 	ITSAMPLESTRUCT itss;
 	BYTE smpcount[MAX_SAMPLES];
 	DWORD inspos[MAX_INSTRUMENTS];
@@ -762,10 +621,9 @@
 	memset(&header, 0, sizeof(header));
 	dwPatNamLen = 0;
 	dwChnNamLen = 0;
-	header.id = 0x4D504D49;
-	lstrcpyn(header.songname, m_szNames[0], 27);
-	header.hilight_minor = m_rowHighlightMinor;
-	header.hilight_major = m_rowHighlightMajor;
+	header.id = 0x4D504D49; // IMPM
+	lstrcpyn((char *)header.songname, m_szNames[0], 27);
+	header.reserved1 = 0x1004;
 	header.ordnum = 0;
 	while ((header.ordnum < MAX_ORDERS) && (Order[header.ordnum] < 0xFF)) header.ordnum++;
 	if (header.ordnum < MAX_ORDERS) Order[header.ordnum++] = 0xFF;
@@ -777,13 +635,16 @@
 	header.cmwt = 0x200;
 	header.flags = 0x0001;
 	header.special = 0x0006;
-	if (m_dwSongFlags & SONG_INSTRUMENTMODE) header.flags |= 0x04;
+	if (m_nInstruments) 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;
@@ -830,7 +691,25 @@
 		header.msgoffset = dwHdrPos + dwExtra + header.insnum*4 + header.patnum*4 + header.smpnum*4;
 	}
 	// Write file header
-	fwrite(&header, 1, sizeof(header), f);
+	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(Order, 1, header.ordnum, f);
 	if (header.insnum) fwrite(inspos, 4, header.insnum, f);
 	if (header.smpnum) fwrite(smppos, 4, header.smpnum, f);
@@ -861,17 +740,19 @@
 	// Writing pattern names
 	if (dwPatNamLen)
 	{
-		DWORD d = 0x4d414e50;
+		DWORD d = bswapLE32(0x4d414e50);
+		UINT len= bswapLE32(dwPatNamLen);
 		fwrite(&d, 1, 4, f);
-		fwrite(&dwPatNamLen, 1, 4, f);
+		write(&len, 1, 4, f);
 		fwrite(m_lpszPatternNames, 1, dwPatNamLen, f);
 	}
 	// Writing channel Names
 	if (dwChnNamLen)
 	{
-		DWORD d = 0x4d414e43;
+		DWORD d = bswapLE32(0x4d414e43);
+		UINT len= bswapLE32(dwChnNamLen);
 		fwrite(&d, 1, 4, f);
-		fwrite(&dwChnNamLen, 1, 4, f);
+		fwrite(&len, 1, 4, f);
 		UINT nChnNames = dwChnNamLen / MAX_CHANNELNAME;
 		for (UINT inam=0; inam<nChnNames; inam++)
 		{
@@ -908,7 +789,7 @@
 			iti.fadeout = penv->nFadeOut >> 5;
 			iti.pps = penv->nPPS;
 			iti.ppc = penv->nPPC;
-			iti.gbv = (BYTE)penv->nGlobalVol;
+			iti.gbv = (BYTE)(penv->nGlobalVol << 1);
 			iti.dfp = (BYTE)penv->nPan >> 2;
 			if (!(penv->dwFlags & ENV_SETPANNING)) iti.dfp |= 0x80;
 			iti.rv = penv->nVolSwing;
@@ -932,44 +813,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->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;
+			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;
 			// 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->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;
+			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;
 			// 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->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;
+			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;
 			// Writing Envelopes data
 			for (UINT ev=0; ev<25; ev++)
 			{
-				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;
+				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;
 			}
 		} else
 		// Save Empty Instrument
@@ -984,7 +865,15 @@
 		// Writing instrument
 		inspos[nins-1] = dwPos;
 		dwPos += sizeof(ITINSTRUMENT);
-		fwrite(&iti, 1, sizeof(ITINSTRUMENT), f);
+
+		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);
 	}
 	// Writing sample headers
 	memset(&itss, 0, sizeof(itss));
@@ -1002,7 +891,7 @@
 		if (!Patterns[npat]) continue;
 		patpos[npat] = dwPos;
 		patinfo[0] = 0;
-		patinfo[1] = PatternSize[npat];
+		patinfo[1] = bswapLE16(PatternSize[npat]);
 		patinfo[2] = 0;
 		patinfo[3] = 0;
 		// Check for empty pattern
@@ -1010,8 +899,7 @@
 		{
 			MODCOMMAND *pzc = Patterns[npat];
 			UINT nz = PatternSize[npat] * m_nChannels;
-                        UINT iz;
-			for (iz=0; iz<nz; iz++)
+			for (UINT iz=0; iz<nz; iz++)
 			{
 				if ((pzc[iz].note) || (pzc[iz].instr)
 				 || (pzc[iz].volcmd) || (pzc[iz].command)) break;
@@ -1038,7 +926,7 @@
 				UINT vol = 0xFF;
 				UINT note = m->note;
 				if (note) b |= 1;
-				if ((note) && (note < 0x80)) note--;
+				if ((note) && (note < 0x80)) note--; // 0xfe->0x80 --Toad
 				if (m->instr) b |= 2;
 				if (m->volcmd)
 				{
@@ -1051,8 +939,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; break;
-					case VOLCMD_VIBRATO:		vol = 203 + ConvertVolParam(m->vol); break;
+					case VOLCMD_VIBRATOSPEED:	vol = 203 + ConvertVolParam(m->vol); break;
+					case VOLCMD_VIBRATO:		vol = 203; 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;
@@ -1146,6 +1034,7 @@
 			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);
 	}
@@ -1158,7 +1047,7 @@
 		memcpy(itss.name, m_szNames[nsmp], 26);
 		itss.id = 0x53504D49;
 		itss.gvl = (BYTE)psmp->nGlobalVol;
-		if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+		if (m_nInstruments)
 		{
 			for (UINT iu=1; iu<=m_nInstruments; iu++) if (Headers[iu])
 			{
@@ -1178,7 +1067,25 @@
 		if (psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40;
 		if (psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80;
 		itss.C5Speed = psmp->nC4Speed;
-		if (!itss.C5Speed) itss.C5Speed = 8363;
+		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;
+		}
+
 		itss.length = psmp->nLength;
 		itss.loopbegin = psmp->nLoopStart;
 		itss.loopend = psmp->nLoopEnd;
@@ -1189,7 +1096,7 @@
 		itss.vit = autovibxm2it[psmp->nVibType & 7];
 		itss.vis = psmp->nVibRate;
 		itss.vid = psmp->nVibDepth;
-		itss.vir = psmp->nVibSweep;
+		itss.vir = (psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255;
 		if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80;
 		if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01;
 		UINT flags = RS_PCM8S;
@@ -1197,7 +1104,7 @@
 		if (nPacking)
 		{
 			if ((!(psmp->uFlags & (CHN_16BIT|CHN_STEREO)))
-			 && (CanPackSample(psmp->pSample, psmp->nLength, nPacking)))
+			 && (CanPackSample((char *)psmp->pSample, psmp->nLength, nPacking)))
 			{
 				flags = RS_ADPCM4;
 				itss.cvt = 0xFF;
@@ -1218,6 +1125,16 @@
 		}
 		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))
@@ -1227,18 +1144,33 @@
 	}
 	// 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
 
-#ifdef MSC_VER
-#pragma warning(default:4100)
-#endif
-
+//#pragma warning(default:4100)
 #endif // MODPLUG_NO_FILESAVE
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1442,7 +1374,8 @@
 {
 	DWORD chinfo[64];
 	CHAR s[32];
-	DWORD nPluginSize;
+	DWORD nPluginSize, writeSwapDWORD;
+	SNDMIXPLUGININFO writePluginInfo;
 	UINT nTotalSize = 0;
 	UINT nChInfo = 0;
 
@@ -1467,9 +1400,23 @@
 				s[2] = '0' + (i/10);
 				s[3] = '0' + (i%10);
 				fwrite(s, 1, 4, f);
-				fwrite(&nPluginSize, 1, 4, f);
-				fwrite(&p->Info, 1, sizeof(SNDMIXPLUGININFO), f);
-				fwrite(&m_MixPlugins[i].nPluginDataSize, 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);
 				if (m_MixPlugins[i].pPluginData)
 				{
 					fwrite(m_MixPlugins[i].pPluginData, 1, m_MixPlugins[i].nPluginDataSize, f);
@@ -1485,6 +1432,7 @@
 			if ((chinfo[j] = ChnSettings[j].nMixPlugin) != 0)
 			{
 				nChInfo = j+1;
+				chinfo[j] = bswapLE32(chinfo[j]); // inplace BS
 			}
 		}
 	}
@@ -1492,10 +1440,11 @@
 	{
 		if (f)
 		{
-			nPluginSize = 0x58464843;
+			nPluginSize = bswapLE32(0x58464843);
 			fwrite(&nPluginSize, 1, 4, f);
 			nPluginSize = nChInfo*4;
-			fwrite(&nPluginSize, 1, 4, f);
+			writeSwapDWORD = bswapLE32(nPluginSize);
+			fwrite(&writeSwapDWORD, 1, 4, f);
 			fwrite(chinfo, 1, nPluginSize, f);
 		}
 		nTotalSize += nChInfo*4 + 8;