changeset 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 6a4d667a9183
children 0cb173caf393 1268886f37ee
files src/modplug/fastmix.cxx src/modplug/it_defs.h src/modplug/load_669.cxx src/modplug/load_amf.cxx src/modplug/load_ams.cxx src/modplug/load_dbm.cxx src/modplug/load_dmf.cxx src/modplug/load_dsm.cxx src/modplug/load_far.cxx src/modplug/load_it.cxx src/modplug/load_mdl.cxx src/modplug/load_med.cxx src/modplug/load_mod.cxx src/modplug/load_mt2.cxx src/modplug/load_mtm.cxx src/modplug/load_okt.cxx src/modplug/load_psm.cxx src/modplug/load_ptm.cxx src/modplug/load_s3m.cxx src/modplug/load_stm.cxx src/modplug/load_ult.cxx src/modplug/load_wav.cxx src/modplug/load_xm.cxx src/modplug/snd_dsp.cxx src/modplug/snd_flt.cxx src/modplug/snd_fx.cxx src/modplug/sndfile.cxx src/modplug/sndfile.h src/modplug/sndmix.cxx src/modplug/stdafx.h src/modplug/tables.cxx
diffstat 31 files changed, 2282 insertions(+), 2120 deletions(-) [+]
line wrap: on
line diff
--- a/src/modplug/fastmix.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/fastmix.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -1,5 +1,8 @@
 /*
- * This source code is public domain.
+ * This program is  free software; you can redistribute it  and modify it
+ * under the terms of the GNU  General Public License as published by the
+ * Free Software Foundation; either version 2  of the license or (at your
+ * option) any later version.
  *
  * Authors: Olivier Lapicque <olivierl@jps.net>
  *          Markus Fick <webmaster@mark-f.de> spline + fir-resampler
@@ -9,6 +12,10 @@
 #include "sndfile.h"
 #include <math.h>
 
+#ifdef MSC_VER
+#pragma bss_seg(".modplug")
+#endif
+
 // Front Mix Buffer (Also room for interleaved rear mix)
 int MixSoundBuffer[MIXBUFFERSIZE*4];
 
@@ -18,8 +25,14 @@
 extern UINT gnReverbSend;
 #endif
 
+#ifndef MODPLUG_FASTSOUNDLIB
 int MixRearBuffer[MIXBUFFERSIZE*2];
 float MixFloatBuffer[MIXBUFFERSIZE*2];
+#endif
+
+#ifdef MSC_VER
+#pragma bss_seg()
+#endif
 
 
 extern LONG gnDryROfsVol;
@@ -517,39 +530,37 @@
 // Resonant Filters
 
 // Mono
-#define MIX_BEGIN_FILTER \
-	double fy1 = pChannel->nFilter_Y1;\
-	double fy2 = pChannel->nFilter_Y2;\
-	double ta;
+#define MIX_BEGIN_FILTER\
+	int fy1 = pChannel->nFilter_Y1;\
+	int fy2 = pChannel->nFilter_Y2;\
 
-#define MIX_END_FILTER \
+#define MIX_END_FILTER\
 	pChannel->nFilter_Y1 = fy1;\
 	pChannel->nFilter_Y2 = fy2;
 
-#define SNDMIX_PROCESSFILTER \
-ta = ((double)vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\
-fy2 = fy1;\
-fy1 = ta;vol=(int)ta;
+#define SNDMIX_PROCESSFILTER\
+	vol = (vol * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
+	fy2 = fy1;\
+	fy1 = vol;\
 
 // Stereo
-#define MIX_BEGIN_STEREO_FILTER \
-double fy1 = pChannel->nFilter_Y1;\
-double fy2 = pChannel->nFilter_Y2;\
-double fy3 = pChannel->nFilter_Y3;\
-double fy4 = pChannel->nFilter_Y4;\
-double ta, tb;
+#define MIX_BEGIN_STEREO_FILTER\
+	int fy1 = pChannel->nFilter_Y1;\
+	int fy2 = pChannel->nFilter_Y2;\
+	int fy3 = pChannel->nFilter_Y3;\
+	int fy4 = pChannel->nFilter_Y4;\
 
-#define MIX_END_STEREO_FILTER \
-pChannel->nFilter_Y1 = fy1;\
-pChannel->nFilter_Y2 = fy2;\
-pChannel->nFilter_Y3 = fy3;\
-pChannel->nFilter_Y4 = fy4;\
+#define MIX_END_STEREO_FILTER\
+	pChannel->nFilter_Y1 = fy1;\
+	pChannel->nFilter_Y2 = fy2;\
+	pChannel->nFilter_Y3 = fy3;\
+	pChannel->nFilter_Y4 = fy4;\
 
-#define SNDMIX_PROCESSSTEREOFILTER \
-ta = ((double)vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1);\
-tb = ((double)vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1);\
-fy2 = fy1; fy1 = ta;vol_l=(int)ta;\
-fy4 = fy3; fy3 = tb;vol_r=(int)tb;
+#define SNDMIX_PROCESSSTEREOFILTER\
+	vol_l = (vol_l * pChn->nFilter_A0 + fy1 * pChn->nFilter_B0 + fy2 * pChn->nFilter_B1 + 4096) >> 13;\
+	vol_r = (vol_r * pChn->nFilter_A0 + fy3 * pChn->nFilter_B0 + fy4 * pChn->nFilter_B1 + 4096) >> 13;\
+	fy2 = fy1; fy1 = vol_l;\
+	fy4 = fy3; fy3 = vol_r;\
 
 //////////////////////////////////////////////////////////
 // Interfaces
@@ -648,17 +659,11 @@
 /////////////////////////////////////////////////////
 //
 
-extern void StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount, const float _i2fc);
-extern void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount, const float _f2ic);
-extern void MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount, const float _i2fc);
-extern void FloatToMonoMix(const float *pIn, int *pOut, UINT nCount, const float _f2ic);
-
-void InitMixBuffer(int *pBuffer, UINT nSamples);
-void EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
-void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
-
-void StereoMixToFloat(const int *, float *, float *, UINT nCount);
-void FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
+void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples);
+void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples);
+void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
+void X86_StereoMixToFloat(const int *, float *, float *, UINT nCount);
+void X86_FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
 
 /////////////////////////////////////////////////////
 // Mono samples functions
@@ -1461,7 +1466,9 @@
 	DWORD nchused, nchmixed;
 
 	if (!count) return 0;
-	if (gnChannels > 2) InitMixBuffer(MixRearBuffer, count*2);
+#ifndef MODPLUG_FASTSOUNDLIB
+	if (gnChannels > 2) X86_InitMixBuffer(MixRearBuffer, count*2);
+#endif
 	nchused = nchmixed = 0;
 	for (UINT nChn=0; nChn<m_nMixChannels; nChn++)
 	{
@@ -1482,16 +1489,15 @@
 	#ifndef NO_FILTER
 		if (pChannel->dwFlags & CHN_FILTER) nFlags |= MIXNDX_FILTER;
 	#endif
-		if (!(pChannel->dwFlags & CHN_NOIDO)
-		&& !(gdwSoundSetup & SNDMIX_NORESAMPLING))
+		if (!(pChannel->dwFlags & CHN_NOIDO))
 		{
 			// use hq-fir mixer?
 			if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE)) == (SNDMIX_HQRESAMPLER|SNDMIX_ULTRAHQSRCMODE) )
-				nFlags |= MIXNDX_FIRSRC;
-			else if( (gdwSoundSetup & SNDMIX_HQRESAMPLER))
-				nFlags |= MIXNDX_SPLINESRC;
+				nFlags += MIXNDX_FIRSRC;
+			else if( (gdwSoundSetup & (SNDMIX_HQRESAMPLER)) == SNDMIX_HQRESAMPLER )
+				nFlags += MIXNDX_SPLINESRC;
 			else
-				nFlags |= MIXNDX_LINEARSRC; // use
+				nFlags += MIXNDX_LINEARSRC; // use
 		}
 		if ((nFlags < 0x40) && (pChannel->nLeftVol == pChannel->nRightVol)
 		 && ((!pChannel->nRampLength) || (pChannel->nLeftRamp == pChannel->nRightRamp)))
@@ -1530,7 +1536,7 @@
 			pChannel->nPos = 0;
 			pChannel->nPosLo = 0;
 			pChannel->nRampLength = 0;
-			EndChannelOfs(pChannel, pbuffer, nsamples);
+			X86_EndChannelOfs(pChannel, pbuffer, nsamples);
 			*pOfsR += pChannel->nROfs;
 			*pOfsL += pChannel->nLOfs;
 			pChannel->nROfs = pChannel->nLOfs = 0;
@@ -1551,10 +1557,6 @@
 		} else
 		// Do mixing
 		{
-			if (pChannel->nLength) {
-				pChannel->topnote_offset = ((pChannel->nPos << 16) | pChannel->nPosLo) % pChannel->nLength;
-			}
-
 			// Choose function for mixing
 			LPMIXINTERFACE pMixFunc;
 			pMixFunc = (pChannel->nRampLength) ? pMixFuncTable[nFlags|MIXNDX_RAMP] : pMixFuncTable[nFlags];
@@ -1591,59 +1593,81 @@
 	return nchused;
 }
 
-static float f2ic = (float)(1 << 28);
-static float i2fc = (float)(1.0 / (1 << 28));
 
-VOID CSoundFile::StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount)
-//-----------------------------------------------------------------------------------------
-{
-	for (UINT i = 0; i < nCount; i++) {
-		*pOut1++ = *pSrc * i2fc; /*!*/
-		pSrc++;
+#ifdef MSC_VER
+#pragma warning (disable:4100)
+#endif
 
-		*pOut2++ = *pSrc * i2fc; /*!*/
-		pSrc++;
-	}
-}
-
-
-VOID CSoundFile::FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount)
-//---------------------------------------------------------------------------------------------
+// Clip and convert to 8 bit
+#ifdef MSC_VER
+__declspec(naked) DWORD MPPASMCALL X86_Convert32To8(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+//----------------------------------------------------------------------------------------------------------------------------
 {
-	for (UINT i = 0; i < nCount; i++) {
-		*pOut++ = (int)(*pIn1 * f2ic);
-		*pOut++ = (int)(*pIn2 * f2ic);
-		pIn1++;
-		pIn2++;
+    _asm {
+        push ebx
+	push esi
+	push edi
+	mov ebx, 16[esp]		// ebx = 8-bit buffer
+	mov esi, 20[esp]		// esi = pBuffer
+	mov edi, 24[esp]		// edi = lSampleCount
+	mov eax, 28[esp]
+	mov ecx, dword ptr [eax]	// ecx = clipmin
+	mov eax, 32[esp]
+	mov edx, dword ptr [eax]	// edx = clipmax
+cliploop:
+	mov eax, dword ptr [esi]
+	inc ebx
+	cdq
+	and edx, (1 << (24-MIXING_ATTENUATION)) - 1
+	add eax, edx
+	cmp eax, MIXING_CLIPMIN
+	jl cliplow
+	cmp eax, MIXING_CLIPMAX
+	jg cliphigh
+	cmp eax, ecx
+	jl updatemin
+	cmp eax, edx
+	jg updatemax
+cliprecover:
+	add esi, 4
+	sar eax, 24-MIXING_ATTENUATION
+	xor eax, 0x80
+	dec edi
+	mov byte ptr [ebx-1], al
+	jnz cliploop
+	mov eax, 28[esp]
+	mov dword ptr [eax], ecx
+	mov eax, 32[esp]
+	mov dword ptr [eax], edx
+	mov eax, 24[esp]
+	pop edi
+	pop esi
+	pop ebx
+	ret
+updatemin:
+	mov ecx, eax
+	jmp cliprecover
+updatemax:
+	mov edx, eax
+	jmp cliprecover
+cliplow:
+	mov ecx, MIXING_CLIPMIN
+	mov edx, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMIN
+	jmp cliprecover
+cliphigh:
+	mov ecx, MIXING_CLIPMIN
+	mov edx, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMAX
+	jmp cliprecover
 	}
 }
-
-
-VOID CSoundFile::MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount)
-//------------------------------------------------------------------------
-{
-	for (UINT i = 0; i < nCount; i++) {
-		*pOut++ = *pSrc * i2fc; /*!*/
-		pSrc++;
-	}
-}
-
-
-VOID CSoundFile::FloatToMonoMix(const float *pIn, int *pOut, UINT nCount)
-//-----------------------------------------------------------------------
-{
-	for (UINT i = 0; i < nCount; i++) {
-		*pOut++ = (int)(*pIn * f2ic); /*!*/
-		pIn++;
-	}
-}
-
-
-// Clip and convert to 8 bit
+#else //MSC_VER
 //---GCCFIX: Asm replaced with C function
 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
-DWORD Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+DWORD MPPASMCALL X86_Convert32To8(LPVOID lp8, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
 {
+	int vumin = *lpMin, vumax = *lpMax;
 	unsigned char *p = (unsigned char *)lp8;
 	for (UINT i=0; i<lSampleCount; i++)
 	{
@@ -1652,18 +1676,92 @@
 			n = MIXING_CLIPMIN;
 		else if (n > MIXING_CLIPMAX)
 			n = MIXING_CLIPMAX;
-		if (n < mins[i&1])
-			mins[i&1]= n;
-		else if (n > maxs[i&1])
-			maxs[i&1] = n;
+		if (n < vumin)
+			vumin = n;
+		else if (n > vumax)
+			vumax = n;
 		p[i] = (n >> (24-MIXING_ATTENUATION)) ^ 0x80;	// 8-bit unsigned
 	}
+	*lpMin = vumin;
+	*lpMax = vumax;
 	return lSampleCount;
 }
+#endif //MSC_VER, else
+
+
+#ifdef MSC_VER
+// Clip and convert to 16 bit
+__declspec(naked) DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+//-----------------------------------------------------------------------------------------------------------------------------
+{
+	_asm {
+	push ebx
+	push esi
+	push edi
+	mov ebx, 16[esp]		// ebx = 16-bit buffer
+	mov eax, 28[esp]
+	mov esi, 20[esp]		// esi = pBuffer
+	mov ecx, dword ptr [eax]	// ecx = clipmin
+	mov edi, 24[esp]		// edi = lSampleCount
+	mov eax, 32[esp]
+	push ebp
+	mov ebp, dword ptr [eax]	// edx = clipmax
+cliploop:
+	mov eax, dword ptr [esi]
+	add ebx, 2
+	cdq
+	and edx, (1 << (16-MIXING_ATTENUATION)) - 1
+	add esi, 4
+	add eax, edx
+	cmp eax, MIXING_CLIPMIN
+	jl cliplow
+	cmp eax, MIXING_CLIPMAX
+	jg cliphigh
+	cmp eax, ecx
+	jl updatemin
+	cmp eax, ebp
+	jg updatemax
+cliprecover:
+	sar eax, 16-MIXING_ATTENUATION
+	dec edi
+	mov word ptr [ebx-2], ax
+	jnz cliploop
+	mov edx, ebp
+	pop ebp
+	mov eax, 28[esp]
+	mov dword ptr [eax], ecx
+	mov eax, 32[esp]
+	mov dword ptr [eax], edx
+	mov eax, 24[esp]
+	pop edi
+	shl eax, 1
+	pop esi
+	pop ebx
+	ret
+updatemin:
+	mov ecx, eax
+	jmp cliprecover
+updatemax:
+	mov ebp, eax
+	jmp cliprecover
+cliplow:
+	mov ecx, MIXING_CLIPMIN
+	mov ebp, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMIN
+	jmp cliprecover
+cliphigh:
+	mov ecx, MIXING_CLIPMIN
+	mov ebp, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMAX
+	jmp cliprecover
+	}
+}
+#else //MSC_VER
 //---GCCFIX: Asm replaced with C function
 // The C version was written by Rani Assaf <rani@magic.metawire.com>, I believe
-DWORD Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+DWORD MPPASMCALL X86_Convert32To16(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
 {
+	int vumin = *lpMin, vumax = *lpMax;
 	signed short *p = (signed short *)lp16;
 	for (UINT i=0; i<lSampleCount; i++)
 	{
@@ -1672,78 +1770,323 @@
 			n = MIXING_CLIPMIN;
 		else if (n > MIXING_CLIPMAX)
 			n = MIXING_CLIPMAX;
-		if (n < mins[i&1])
-			mins[i&1]= n;
-		else if (n > maxs[i&1])
-			maxs[i&1] = n;
+		if (n < vumin)
+			vumin = n;
+		else if (n > vumax)
+			vumax = n;
 		p[i] = n >> (16-MIXING_ATTENUATION);	// 16-bit signed
 	}
+	*lpMin = vumin;
+	*lpMax = vumax;
 	return lSampleCount * 2;
 }
+#endif //MSC_VER, else
+
+#ifdef MSC_VER
+// Clip and convert to 24 bit
+__declspec(naked) DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+//-----------------------------------------------------------------------------------------------------------------------------
+{
+	_asm {
+	push ebx
+	push esi
+	push edi
+	mov ebx, 16[esp]		// ebx = 8-bit buffer
+	mov esi, 20[esp]		// esi = pBuffer
+	mov edi, 24[esp]		// edi = lSampleCount
+	mov eax, 28[esp]
+	mov ecx, dword ptr [eax]	// ecx = clipmin
+	mov eax, 32[esp]
+	push ebp
+	mov edx, dword ptr [eax]	// edx = clipmax
+cliploop:
+	mov eax, dword ptr [esi]
+	mov ebp, eax
+	sar ebp, 31
+	and ebp, (1 << (8-MIXING_ATTENUATION)) - 1
+	add eax, ebp
+	cmp eax, MIXING_CLIPMIN
+	jl cliplow
+	cmp eax, MIXING_CLIPMAX
+	jg cliphigh
+	cmp eax, ecx
+	jl updatemin
+	cmp eax, edx
+	jg updatemax
+cliprecover:
+	add ebx, 3
+	sar eax, 8-MIXING_ATTENUATION
+	add esi, 4
+	mov word ptr [ebx-3], ax
+	shr eax, 16
+	dec edi
+	mov byte ptr [ebx-1], al
+	jnz cliploop
+	pop ebp
+	mov eax, 28[esp]
+	mov dword ptr [eax], ecx
+	mov eax, 32[esp]
+	mov dword ptr [eax], edx
+	mov edx, 24[esp]
+	mov eax, edx
+	pop edi
+	shl eax, 1
+	pop esi
+	add eax, edx
+	pop ebx
+	ret
+updatemin:
+	mov ecx, eax
+	jmp cliprecover
+updatemax:
+	mov edx, eax
+	jmp cliprecover
+cliplow:
+	mov ecx, MIXING_CLIPMIN
+	mov edx, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMIN
+	jmp cliprecover
+cliphigh:
+	mov ecx, MIXING_CLIPMIN
+	mov edx, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMAX
+	jmp cliprecover
+	}
+}
+#else //MSC_VER
 //---GCCFIX: Asm replaced with C function
-// 24-bit might not work...
-DWORD Convert32To24(LPVOID lp24, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+DWORD MPPASMCALL X86_Convert32To24(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
 {
-	/* the inventor of 24bit anything should be shot */
-	unsigned char *p = (unsigned char *)lp24;
-	for (UINT i=0; i<lSampleCount; i++)
+	UINT i ;
+	int vumin = *lpMin, vumax = *lpMax;
+	int n,p ;
+	unsigned char* buf = (unsigned char*)lp16 ;
+	
+	for ( i=0; i<lSampleCount; i++)
+	{
+		n = pBuffer[i];
+		if (n < MIXING_CLIPMIN)
+			n = MIXING_CLIPMIN;
+		else if (n > MIXING_CLIPMAX)
+			n = MIXING_CLIPMAX;
+		if (n < vumin)
+			vumin = n;
+		else if (n > vumax)
+			vumax = n;
+		p = n >> (8-MIXING_ATTENUATION) ; // 24-bit signed
+//		buf[i*3]   = p & 0xFF0000 ; //XXX
+//		buf[i*3+1] = p & 0x00FF00 ;
+//		buf[i*3+2] = p & 0x0000FF ;
+		buf[i*3]   = (p & 0xFF0000) >> 16 ;
+		buf[i*3+1] = (p & 0x00FF00) >> 8 ;
+		buf[i*3+2] = p & 0x0000FF ;
+	}
+	*lpMin = vumin;
+	*lpMax = vumax;
+	return lSampleCount * 3;
+}
+#endif
+
+#ifdef MSC_VER
+// Clip and convert to 32 bit
+__declspec(naked) DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+//-----------------------------------------------------------------------------------------------------------------------------
+{
+	_asm {
+	push ebx
+	push esi
+	push edi
+	mov ebx, 16[esp]			// ebx = 32-bit buffer
+	mov esi, 20[esp]			// esi = pBuffer
+	mov edi, 24[esp]			// edi = lSampleCount
+	mov eax, 28[esp]
+	mov ecx, dword ptr [eax]	// ecx = clipmin
+	mov eax, 32[esp]
+	mov edx, dword ptr [eax]	// edx = clipmax
+cliploop:
+	mov eax, dword ptr [esi]
+	add ebx, 4
+	add esi, 4
+	cmp eax, MIXING_CLIPMIN
+	jl cliplow
+	cmp eax, MIXING_CLIPMAX
+	jg cliphigh
+	cmp eax, ecx
+	jl updatemin
+	cmp eax, edx
+	jg updatemax
+cliprecover:
+	shl eax, MIXING_ATTENUATION
+	dec edi
+	mov dword ptr [ebx-4], eax
+	jnz cliploop
+	mov eax, 28[esp]
+	mov dword ptr [eax], ecx
+	mov eax, 32[esp]
+	mov dword ptr [eax], edx
+	mov edx, 24[esp]
+	pop edi
+	mov eax, edx
+	pop esi
+	shl eax, 2
+	pop ebx
+	ret
+updatemin:
+	mov ecx, eax
+	jmp cliprecover
+updatemax:
+	mov edx, eax
+	jmp cliprecover
+cliplow:
+	mov ecx, MIXING_CLIPMIN
+	mov edx, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMIN
+	jmp cliprecover
+cliphigh:
+	mov ecx, MIXING_CLIPMIN
+	mov edx, MIXING_CLIPMAX
+	mov eax, MIXING_CLIPMAX
+	jmp cliprecover
+	}
+}
+#else
+//---GCCFIX: Asm replaced with C function
+DWORD MPPASMCALL X86_Convert32To32(LPVOID lp16, int *pBuffer, DWORD lSampleCount, LPLONG lpMin, LPLONG lpMax)
+{
+	UINT i ;
+	int vumin = *lpMin, vumax = *lpMax;
+	signed long *p = (signed long *)lp16;
+	
+	for ( i=0; i<lSampleCount; i++)
 	{
 		int n = pBuffer[i];
 		if (n < MIXING_CLIPMIN)
 			n = MIXING_CLIPMIN;
 		else if (n > MIXING_CLIPMAX)
 			n = MIXING_CLIPMAX;
-		if (n < mins[i&1])
-			mins[i&1]= n;
-		else if (n > maxs[i&1])
-			maxs[i&1] = n;
-		n = n >> (8-MIXING_ATTENUATION);	// 24-bit signed
-		/* err, assume same endian */
-		memcpy(p, &n, 3);
-		p += 3;
+		if (n < vumin)
+			vumin = n;
+		else if (n > vumax)
+			vumax = n;
+		p[i] = n << MIXING_ATTENUATION;	// 32-bit signed
 	}
-	return lSampleCount * 2;
+	*lpMin = vumin;
+	*lpMax = vumax;
+	return lSampleCount * 4;
 }
-//---GCCFIX: Asm replaced with C function
-// 32-bit might not work...
-DWORD Convert32To32(LPVOID lp32, int *pBuffer, DWORD lSampleCount, LONG mins[2], LONG maxs[2])
+#endif
+
+
+#ifdef MSC_VER
+void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
+//------------------------------------------------------------
 {
-	signed int *p = (signed int *)lp32;
-	for (UINT i=0; i<lSampleCount; i++)
-	{
-		int n = pBuffer[i];
-		if (n < MIXING_CLIPMIN)
-			n = MIXING_CLIPMIN;
-		else if (n > MIXING_CLIPMAX)
-			n = MIXING_CLIPMAX;
-		if (n < mins[i&1])
-			mins[i&1]= n;
-		else if (n > maxs[i&1])
-			maxs[i&1] = n;
-		p[i] = (n >> MIXING_ATTENUATION);	// 32-bit signed
+	_asm {
+	mov ecx, nSamples
+	mov esi, pBuffer
+	xor eax, eax
+	mov edx, ecx
+	shr ecx, 2
+	and edx, 3
+	jz unroll4x
+loop1x:
+	add esi, 4
+	dec edx
+	mov dword ptr [esi-4], eax
+	jnz loop1x
+unroll4x:
+	or ecx, ecx
+	jnz loop4x
+	jmp done
+loop4x:
+	add esi, 16
+	dec ecx
+	mov dword ptr [esi-16], eax
+	mov dword ptr [esi-12], eax
+	mov dword ptr [esi-8], eax
+	mov dword ptr [esi-4], eax
+	jnz loop4x
+done:;
 	}
-	return lSampleCount * 2;
 }
+#else
 //---GCCFIX: Asm replaced with C function
 // Will fill in later.
-void InitMixBuffer(int *pBuffer, UINT nSamples)
+void MPPASMCALL X86_InitMixBuffer(int *pBuffer, UINT nSamples)
 {
 	memset(pBuffer, 0, nSamples * sizeof(int));
 }
+#endif
 
-//---GCCFIX: Asm replaced with C function
-void InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
+
+#ifdef MSC_VER
+__declspec(naked) void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
+//------------------------------------------------------------------------------------------------------
 {
-	DWORD i=0;
-
-	pRearBuf[i] = pFrontBuf[1];
-	for (i = 1; i < nSamples; i++) {
-		pRearBuf[i] = pFrontBuf[(i*2)+1];
-		pFrontBuf[i] = pFrontBuf[i*2];
+	_asm {
+	push ebx
+	push ebp
+	push esi
+	push edi
+	mov ecx, 28[esp] // ecx = samplecount
+	mov esi, 20[esp] // esi = front buffer
+	mov edi, 24[esp] // edi = rear buffer
+	lea esi, [esi+ecx*4]	// esi = &front[N]
+	lea edi, [edi+ecx*4]	// edi = &rear[N]
+	lea ebx, [esi+ecx*4]	// ebx = &front[N*2]
+interleaveloop:
+	mov eax, dword ptr [esi-8]
+	mov edx, dword ptr [esi-4]
+	sub ebx, 16
+	mov ebp, dword ptr [edi-8]
+	mov dword ptr [ebx], eax
+	mov dword ptr [ebx+4], edx
+	mov eax, dword ptr [edi-4]
+	sub esi, 8
+	sub edi, 8
+	dec ecx
+	mov dword ptr [ebx+8], ebp
+	mov dword ptr [ebx+12], eax
+	jnz interleaveloop
+	pop edi
+	pop esi
+	pop ebp
+	pop ebx
+	ret
 	}
 }
+#else
 //---GCCFIX: Asm replaced with C function
-VOID MonoFromStereo(int *pMixBuf, UINT nSamples)
+// Multichannel not supported.
+void MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples)
+{
+}
+#endif
+
+
+#ifdef MSC_VER
+VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
+//-------------------------------------------------------------
+{
+	_asm {
+	mov ecx, nSamples
+	mov esi, pMixBuf
+	mov edi, esi
+stloop:
+	mov eax, dword ptr [esi]
+	mov edx, dword ptr [esi+4]
+	add edi, 4
+	add esi, 8
+	add eax, edx
+	sar eax, 1
+	dec ecx
+	mov dword ptr [edi-4], eax
+	jnz stloop
+	}
+}
+#else
+//---GCCFIX: Asm replaced with C function
+VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples)
 {
 	UINT j;
 	for(UINT i = 0; i < nSamples; i++)
@@ -1752,11 +2095,89 @@
 		pMixBuf[i] = (pMixBuf[j] + pMixBuf[j + 1]) >> 1;
 	}
 }
+#endif
 
+#define OFSDECAYSHIFT	8
+#define OFSDECAYMASK	0xFF
+
+
+#ifdef MSC_VER
+void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
+//---------------------------------------------------------------------------------------
+{
+	_asm {
+	mov edi, pBuffer
+	mov ecx, nSamples
+	mov eax, lpROfs
+	mov edx, lpLOfs
+	mov eax, [eax]
+	mov edx, [edx]
+	or ecx, ecx
+	jz fill_loop
+	mov ebx, eax
+	or ebx, edx
+	jz fill_loop
+ofsloop:
+	mov ebx, eax
+	mov esi, edx
+	neg ebx
+	neg esi
+	sar ebx, 31
+	sar esi, 31
+	and ebx, OFSDECAYMASK
+	and esi, OFSDECAYMASK
+	add ebx, eax
+	add esi, edx
+	sar ebx, OFSDECAYSHIFT
+	sar esi, OFSDECAYSHIFT
+	sub eax, ebx
+	sub edx, esi
+	mov ebx, eax
+	or ebx, edx
+	jz fill_loop
+	add edi, 8
+	dec ecx
+	mov [edi-8], eax
+	mov [edi-4], edx
+	jnz ofsloop
+fill_loop:
+	mov ebx, ecx
+	and ebx, 3
+	jz fill4x
+fill1x:
+	mov [edi], eax
+	mov [edi+4], edx
+	add edi, 8
+	dec ebx
+	jnz fill1x
+fill4x:
+	shr ecx, 2
+	or ecx, ecx
+	jz done
+fill4xloop:
+	mov [edi], eax
+	mov [edi+4], edx
+	mov [edi+8], eax
+	mov [edi+12], edx
+	add edi, 8*4
+	dec ecx
+	mov [edi-16], eax
+	mov [edi-12], edx
+	mov [edi-8], eax
+	mov [edi-4], edx
+	jnz fill4xloop
+done:
+	mov esi, lpROfs
+	mov edi, lpLOfs
+	mov [esi], eax
+	mov [edi], edx
+	}
+}
+#else
 //---GCCFIX: Asm replaced with C function
 #define OFSDECAYSHIFT    8
 #define OFSDECAYMASK     0xFF
-void StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
+void MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs)
 //---------------------------------------------------------------------------------------------------------
 {
 	int rofs = *lpROfs;
@@ -1764,7 +2185,7 @@
 
 	if ((!rofs) && (!lofs))
 	{
-		InitMixBuffer(pBuffer, nSamples*2);
+		X86_InitMixBuffer(pBuffer, nSamples*2);
 		return;
 	}
 	for (UINT i=0; i<nSamples; i++)
@@ -1779,9 +2200,53 @@
 	*lpROfs = rofs;
 	*lpLOfs = lofs;
 }
+#endif
+
+#ifdef MSC_VER
+void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
+//----------------------------------------------------------------------------------
+{
+	_asm {
+	mov esi, pChannel
+	mov edi, pBuffer
+	mov ecx, nSamples
+	mov eax, dword ptr [esi+MODCHANNEL.nROfs]
+	mov edx, dword ptr [esi+MODCHANNEL.nLOfs]
+	or ecx, ecx
+	jz brkloop
+ofsloop:
+	mov ebx, eax
+	mov esi, edx
+	neg ebx
+	neg esi
+	sar ebx, 31
+	sar esi, 31
+	and ebx, OFSDECAYMASK
+	and esi, OFSDECAYMASK
+	add ebx, eax
+	add esi, edx
+	sar ebx, OFSDECAYSHIFT
+	sar esi, OFSDECAYSHIFT
+	sub eax, ebx
+	sub edx, esi
+	mov ebx, eax
+	add dword ptr [edi], eax
+	add dword ptr [edi+4], edx
+	or ebx, edx
+	jz brkloop
+	add edi, 8
+	dec ecx
+	jnz ofsloop
+brkloop:
+	mov esi, pChannel
+	mov dword ptr [esi+MODCHANNEL.nROfs], eax
+	mov dword ptr [esi+MODCHANNEL.nLOfs], edx
+	}
+}
+#else
 //---GCCFIX: Asm replaced with C function
 // Will fill in later.
-void EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
+void MPPASMCALL X86_EndChannelOfs(MODCHANNEL *pChannel, int *pBuffer, UINT nSamples)
 {
 	int rofs = pChannel->nROfs;
 	int lofs = pChannel->nLOfs;
@@ -1799,9 +2264,7 @@
 	pChannel->nROfs = rofs;
 	pChannel->nLOfs = lofs;
 }
-
-
-
+#endif
 
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -1813,11 +2276,72 @@
 #define MIXING_LIMITMAX		(0x08100000)
 #define MIXING_LIMITMIN		(-MIXING_LIMITMAX)
 
+#ifdef MSC_VER
+__declspec(naked) UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
+//-------------------------------------------------------------------------------
+{
+	__asm {
+	push ebx
+	push ebp
+	push esi
+	push edi
+	mov esi, 20[esp]	// esi = pBuffer+i
+	mov ecx, 24[esp]	// ecx = i
+	mov edi, 28[esp]	// edi = AGC (0..256)
+agcloop:
+	mov eax, dword ptr [esi]
+	imul edi
+	shrd eax, edx, AGC_PRECISION
+	add esi, 4
+	cmp eax, MIXING_LIMITMIN
+	jl agcupdate
+	cmp eax, MIXING_LIMITMAX
+	jg agcupdate
+agcrecover:
+	dec ecx
+	mov dword ptr [esi-4], eax
+	jnz agcloop
+	mov eax, edi
+	pop edi
+	pop esi
+	pop ebp
+	pop ebx
+	ret
+agcupdate:
+	dec edi
+	jmp agcrecover
+	}
+}
+
+#pragma warning (default:4100)
+#else
+// Version for GCC
+UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC)
+{
+	int x;
+
+	while(nSamples)
+	{
+		x = ((long long int)(*pBuffer) * nAGC) >> AGC_PRECISION;
+
+		if((x < MIXING_LIMITMIN) || (x > MIXING_LIMITMAX))
+		nAGC--;
+
+		*pBuffer = x;
+
+		pBuffer++;
+		nSamples--;
+	}
+
+	return nAGC;
+}
+#endif
+
 void CSoundFile::ProcessAGC(int count)
 //------------------------------------
 {
 	static DWORD gAGCRecoverCount = 0;
-	UINT agc = AGC(MixSoundBuffer, count, gnAGC);
+	UINT agc = X86_AGC(MixSoundBuffer, count, gnAGC);
 	// Some kind custom law, so that the AGC stays quite stable, but slowly
 	// goes back up if the sound level stays below a level inversely proportional
 	// to the AGC level. (J'me comprends)
@@ -1847,4 +2371,3 @@
 }
 
 #endif // NO_AGC
-
--- a/src/modplug/it_defs.h	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/it_defs.h	Fri Dec 07 12:13:37 2007 -0600
@@ -7,8 +7,7 @@
 {
 	DWORD id;			// 0x4D504D49
 	CHAR songname[26];
-	BYTE hilight_minor;
-	BYTE hilight_major;
+	WORD reserved1;		// 0x1004
 	WORD ordnum;
 	WORD insnum;
 	WORD smpnum;
@@ -22,7 +21,7 @@
 	BYTE speed;
 	BYTE tempo;
 	BYTE sep;
-	BYTE pwd;
+	BYTE zero;
 	WORD msglength;
 	DWORD msgoffset;
 	DWORD reserved2;
--- a/src/modplug/load_669.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_669.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -51,9 +51,12 @@
 	 || (!pfh->patterns) || (pfh->patterns > 128)) return FALSE;
 	DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600;
 	if (dontfuckwithme > dwMemLength) return FALSE;
-        for (int n = 0; n < 128; n++)
-                if (pfh->breaks[n] > 0x3f)
-                        return false;
+	for (UINT ichk=0; ichk<pfh->samples; ichk++)
+	{
+		DWORD len = bswapLE32(*((DWORD *)(&psmp[ichk].length)));
+		dontfuckwithme += len;
+	}
+	if (dontfuckwithme > dwMemLength) return FALSE;
 	// That should be enough checking: this must be a 669 module.
 	m_nType = MOD_TYPE_669;
 	m_dwSongFlags |= SONG_LINEARSLIDES;
@@ -62,8 +65,7 @@
 	m_nDefaultTempo = 125;
 	m_nDefaultSpeed = 6;
 	m_nChannels = 8;
-	memcpy(m_szNames[0], pfh->songmessage, 31);
-	m_szNames[0][31] = 0;
+	memcpy(m_szNames[0], pfh->songmessage, 16);
 	m_nSamples = pfh->samples;
 	for (UINT nins=1; nins<=m_nSamples; nins++, psmp++)
 	{
@@ -84,15 +86,9 @@
 		Ins[nins].nPan = 128;
 	}
 	// Song Message
-	m_lpszSongComments = new char[114];
-	memcpy(m_lpszSongComments, pfh->songmessage, 36);
-	m_lpszSongComments[36] = '\015';
-	m_lpszSongComments[37] = '\012';
-	memcpy(m_lpszSongComments + 38, pfh->songmessage + 36, 36);
-	m_lpszSongComments[74] = '\015';
-	m_lpszSongComments[75] = '\012';
-	memcpy(m_lpszSongComments + 76, pfh->songmessage + 72, 36);
-	m_lpszSongComments[112] = 0;
+	m_lpszSongComments = new char[109];
+	memcpy(m_lpszSongComments, pfh->songmessage, 108);
+	m_lpszSongComments[108] = 0;
 	// Reading Orders
 	memcpy(Order, pfh->orders, 128);
 	m_nRestartPos = pfh->restartpos;
@@ -110,7 +106,6 @@
 		Patterns[npat] = AllocatePattern(64, m_nChannels);
 		if (!Patterns[npat]) break;
 		PatternSize[npat] = 64;
-		PatternAllocSize[npat] = 64;
 		MODCOMMAND *m = Patterns[npat];
 		const BYTE *p = lpStream + dwMemPos;
 		for (UINT row=0; row<64; row++)
--- a/src/modplug/load_amf.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_amf.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -1,8 +1,11 @@
 /*
- * This source code is public domain.
+ * This program is  free software; you can redistribute it  and modify it
+ * under the terms of the GNU  General Public License as published by the
+ * Free Software Foundation; either version 2  of the license or (at your
+ * option) any later version.
  *
  * Authors: Olivier Lapicque <olivierl@jps.net>
- */
+*/
 
 ///////////////////////////////////////////////////
 //
@@ -220,7 +223,6 @@
 			if (!p) break;
 			Patterns[iPat] = p;
 			PatternSize[iPat] = 64;
-			PatternAllocSize[iPat] = 64;
 			const UCHAR *pin = lpStream + dwMemPos;
 			for (UINT i=0; i<8*64; i++)
 			{
@@ -312,11 +314,9 @@
 		{
 			Order[iOrd] = iOrd;
 			PatternSize[iOrd] = 64;
-			PatternAllocSize[iOrd] = 64;
 			if (pfh->version >= 14)
 			{
 				PatternSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos));
-				PatternAllocSize[iOrd] = bswapLE16(*(USHORT *)(lpStream+dwMemPos));
 				dwMemPos += 2;
 			}
 			ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos);
@@ -353,7 +353,8 @@
 		if ((psh->type) && (bswapLE32(psh->offset) < dwMemLength-1))
 		{
 			sampleseekpos[iIns] = bswapLE32(psh->offset);
-			if (bswapLE32(psh->offset) > maxsampleseekpos) maxsampleseekpos = bswapLE32(psh->offset);
+			if (bswapLE32(psh->offset) > maxsampleseekpos) 
+				maxsampleseekpos = bswapLE32(psh->offset);
 			if ((pins->nLoopEnd > pins->nLoopStart + 2)
 			 && (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP;
 		}
@@ -417,5 +418,3 @@
 	}
 	return TRUE;
 }
-
-
--- a/src/modplug/load_ams.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_ams.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -142,7 +142,6 @@
 		dwMemPos += 4;
 		if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return TRUE;
 		PatternSize[iPat] = 64;
-		PatternAllocSize[iPat] = 64;
 		MODCOMMAND *m = AllocatePattern(PatternSize[iPat], m_nChannels);
 		if (!m) return TRUE;
 		Patterns[iPat] = m;
@@ -335,7 +334,6 @@
 	m_nDefaultSpeed = psh->speed;
 	m_nInstruments = psh->instruments;
 	m_nSamples = 0;
-	m_dwSongFlags |= SONG_INSTRUMENTMODE;
 	if (psh->flags & 0x40) m_dwSongFlags |= SONG_LINEARSLIDES;
 	for (UINT nIns=1; nIns<=m_nInstruments; nIns++)
 	{
@@ -380,15 +378,15 @@
 		// Volume Envelope
 		{
 			UINT pos = 0;
-			penv->VolEnv.nNodes = (volenv->points > 16) ? 16 : volenv->points;
-			penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = volenv->sustain;
-			penv->VolEnv.nLoopStart = volenv->loopbegin;
-			penv->VolEnv.nLoopEnd = volenv->loopend;
-			for (int i=0; i<penv->VolEnv.nNodes; i++)
+			penv->nVolEnv = (volenv->points > 16) ? 16 : volenv->points;
+			penv->nVolSustainBegin = penv->nVolSustainEnd = volenv->sustain;
+			penv->nVolLoopStart = volenv->loopbegin;
+			penv->nVolLoopEnd = volenv->loopend;
+			for (UINT i=0; i<penv->nVolEnv; i++)
 			{
-				penv->VolEnv.Values[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
+				penv->VolEnv[i] = (BYTE)((volenv->info[i*3+2] & 0x7F) >> 1);
 				pos += volenv->info[i*3] + ((volenv->info[i*3+1] & 1) << 8);
-				penv->VolEnv.Ticks[i] = (WORD)pos;
+				penv->VolPoints[i] = (WORD)pos;
 			}
 		}
 		penv->nFadeOut = (((lpStream[dwMemPos+2] & 0x0F) << 8) | (lpStream[dwMemPos+1])) << 3;
@@ -489,7 +487,6 @@
 				SetPatternName(ipat, s);
 			}
 			PatternSize[ipat] = numrows;
-			PatternAllocSize[ipat] = numrows;
 			Patterns[ipat] = AllocatePattern(numrows, m_nChannels);
 			if (!Patterns[ipat]) return TRUE;
 			// Unpack Pattern Data
--- a/src/modplug/load_dbm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_dbm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -158,7 +158,7 @@
 				}
 				Headers[iIns+1] = penv;
 				penv->nFadeOut = 1024;	// ???
-				penv->nGlobalVol = 128;
+				penv->nGlobalVol = 64;
 				penv->nPan = bswapBE16(pih->panning);
 				if ((penv->nPan) && (penv->nPan < 256))
 					penv->dwFlags = ENV_SETPANNING;
@@ -193,7 +193,6 @@
 				chunk_pos += sizeof(DBMINSTRUMENT);
 				m_nInstruments = iIns+1;
 			}
-			m_dwSongFlags |= SONG_INSTRUMENTMODE;
 		} else
 		// Volume Envelopes
 		if (chunk_id == DBM_ID_VENV)
@@ -216,15 +215,15 @@
 					if (peh->flags & 1) penv->dwFlags |= ENV_VOLUME;
 					if (peh->flags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
 					if (peh->flags & 4) penv->dwFlags |= ENV_VOLLOOP;
-					penv->VolEnv.nNodes = peh->numpoints + 1;
-					if (penv->VolEnv.nNodes > MAX_ENVPOINTS) penv->VolEnv.nNodes = MAX_ENVPOINTS;
-					penv->VolEnv.nLoopStart = peh->loopbegin;
-					penv->VolEnv.nLoopEnd = peh->loopend;
-					penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = peh->sustain1;
-					for (int i=0; i<penv->VolEnv.nNodes; i++)
+					penv->nVolEnv = peh->numpoints + 1;
+					if (penv->nVolEnv > MAX_ENVPOINTS) penv->nVolEnv = MAX_ENVPOINTS;
+					penv->nVolLoopStart = peh->loopbegin;
+					penv->nVolLoopEnd = peh->loopend;
+					penv->nVolSustainBegin = penv->nVolSustainEnd = peh->sustain1;
+					for (UINT i=0; i<penv->nVolEnv; i++)
 					{
-						penv->VolEnv.Ticks[i] = bswapBE16(peh->volenv[i*2]);
-						penv->VolEnv.Values[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]);
+						penv->VolPoints[i] = bswapBE16(peh->volenv[i*2]);
+						penv->VolEnv[i] = (BYTE)bswapBE16(peh->volenv[i*2+1]);
 					}
 				}
 				chunk_pos += sizeof(DBMENVELOPE);
@@ -255,7 +254,6 @@
 						UINT i = 0;
 
 						PatternSize[iPat] = nRows;
-						PatternAllocSize[iPat] = nRows;
 						Patterns[iPat] = m;
 						while ((i+3<pksize) && (row < nRows))
 						{
--- a/src/modplug/load_dmf.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_dmf.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -176,7 +176,6 @@
 					dwPos += 8;
 					if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break;
 					PatternSize[npat] = (WORD)ticks;
-					PatternAllocSize[npat] = (WORD)ticks;
 					MODCOMMAND *m = AllocatePattern(PatternSize[npat], m_nChannels);
 					if (!m) goto dmfexit;
 					Patterns[npat] = m;
--- a/src/modplug/load_dsm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_dsm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -136,7 +136,6 @@
 			MODCOMMAND *m = AllocatePattern(64, m_nChannels);
 			if (!m) break;
 			PatternSize[nPat] = 64;
-			PatternAllocSize[nPat] = 64;
 			Patterns[nPat] = m;
 			UINT row = 0;
 			while ((row < 64) && (dwPos + 2 <= dwMemPos))
--- a/src/modplug/load_far.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_far.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -64,9 +64,10 @@
 	UINT headerlen;
 	BYTE samplemap[8];
 
-	if ((!lpStream) || (dwMemLength < 1024) || (pmh1->id != FARFILEMAGIC)
+	if ((!lpStream) || (dwMemLength < 1024) || (bswapLE32(pmh1->id) != FARFILEMAGIC)
 	 || (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE;
-	headerlen = pmh1->headerlen;
+	headerlen = bswapLE16(pmh1->headerlen);
+	pmh1->stlen = bswapLE16( pmh1->stlen ); /* inplace byteswap -- Toad */
 	if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE;
 	// Globals
 	m_nType = MOD_TYPE_FAR;
@@ -111,6 +112,14 @@
 	dwMemPos += headerlen - (869 + pmh1->stlen);
 	if (dwMemPos >= dwMemLength) return TRUE;
 
+	// byteswap pattern data -- Toad
+	UINT psfix = 0 ;
+	while( psfix++ < 256 )
+	{
+		pmh2->patsiz[psfix] = bswapLE16( pmh2->patsiz[psfix] ) ;
+	}
+	// end byteswap of pattern data
+
 	WORD *patsiz = (WORD *)pmh2->patsiz;
 	for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat])
 	{
@@ -130,7 +139,6 @@
 		if (rows > 256) rows = 256;
 		if (rows < 16) rows = 16;
 		PatternSize[ipat] = rows;
-		PatternAllocSize[ipat] = rows;
 		if ((Patterns[ipat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
 		MODCOMMAND *m = Patterns[ipat];
 		UINT patbrk = lpStream[dwMemPos];
@@ -233,9 +241,10 @@
 		dwMemPos += sizeof(FARSAMPLE);
 		m_nSamples = ismp + 1;
 		memcpy(m_szNames[ismp+1], pfs->samplename, 32);
-		pins->nLength = pfs->length;
-		pins->nLoopStart = pfs->reppos;
-		pins->nLoopEnd = pfs->repend;
+		pfs->length = bswapLE32( pfs->length ) ; /* endian fix - Toad */
+		pins->nLength = pfs->length ;
+		pins->nLoopStart = bswapLE32(pfs->reppos) ;
+		pins->nLoopEnd = bswapLE32(pfs->repend) ;
 		pins->nFineTune = 0;
 		pins->nC4Speed = 8363*2;
 		pins->nGlobalVol = 64;
--- 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;
--- a/src/modplug/load_mdl.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_mdl.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -76,31 +76,8 @@
 		}
 		break;
 	case 0x0F:	command = CMD_SPEED; break;
-                
-	case 0x10:
-                if ((param & 0xF0) != 0xE0) {
-                        command = CMD_VOLUMESLIDE;
-                        if ((param & 0xF0) == 0xF0) {
-                                param = ((param << 4) | 0x0F);
-                        } else {
-                                param >>= 2;
-                                if (param > 0xF)
-                                        param = 0xF;
-                                param <<= 4;
-                        }
-                }
-                break;
-	case 0x20:
-                if ((param & 0xF0) != 0xE0) {
-                        command = CMD_VOLUMESLIDE;
-                        if ((param & 0xF0) != 0xF0) {
-                                param >>= 2;
-                                if (param > 0xF)
-                                        param = 0xF;
-                        }
-                }
-                break;
-                
+	case 0x10:	if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) == 0xF0) param = ((param << 4) | 0x0F); else param >>= 2; } break;
+	case 0x20:	if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } break;
 	case 0x30:	command = CMD_RETRIG; break;
 	case 0x40:	command = CMD_TREMOLO; break;
 	case 0x50:	command = CMD_TREMOR; break;
@@ -217,7 +194,7 @@
 	UINT nvolenv, npanenv, npitchenv;
 
 	if ((!lpStream) || (dwMemLength < 1024)) return FALSE;
-	if ((bswapLE32(pmsh->id) != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE;
+	if ((pmsh->id != 0x4C444D44) || ((pmsh->version & 0xF0) > 0x10)) return FALSE;
 	memset(patterntracks, 0, sizeof(patterntracks));
 	memset(smpinfo, 0, sizeof(smpinfo));
 	memset(insvolenv, 0, sizeof(insvolenv));
@@ -227,13 +204,10 @@
 	pvolenv = ppanenv = ppitchenv = NULL;
 	nvolenv = npanenv = npitchenv = 0;
 	m_nSamples = m_nInstruments = 0;
-	m_dwSongFlags |= SONG_INSTRUMENTMODE;
 	while (dwMemPos+6 < dwMemLength)
 	{
 		block = *((WORD *)(lpStream+dwMemPos));
 		blocklen = *((DWORD *)(lpStream+dwMemPos+2));
-		block = bswapLE16(block);
-		blocklen = bswapLE32(blocklen);
 		dwMemPos += 6;
 		if (dwMemPos + blocklen > dwMemLength)
 		{
@@ -246,12 +220,10 @@
 		case 0x4E49:
 			pmib = (MDLINFOBLOCK *)(lpStream+dwMemPos);
 			memcpy(m_szNames[0], pmib->songname, 32);
-			norders = bswapLE16(pmib->norders);
+			norders = pmib->norders;
 			if (norders > MAX_ORDERS) norders = MAX_ORDERS;
-			m_nRestartPos = bswapLE16(pmib->repeatpos);
+			m_nRestartPos = pmib->repeatpos;
 			m_nDefaultGlobalVolume = pmib->globalvol;
-                        if (m_nDefaultGlobalVolume == 255)
-                                m_nDefaultGlobalVolume++;
 			m_nDefaultTempo = pmib->tempo;
 			m_nDefaultSpeed = pmib->speed;
 			m_nChannels = 4;
@@ -290,12 +262,11 @@
 				pmpd = (MDLPATTERNDATA *)(lpStream + dwPos);
 				if (pmpd->channels > 32) break;
 				PatternSize[i] = pmpd->lastrow+1;
-				PatternAllocSize[i] = pmpd->lastrow+1;
 				if (m_nChannels < pmpd->channels) m_nChannels = pmpd->channels;
 				dwPos += 18 + 2*pmpd->channels;
 				for (j=0; j<pmpd->channels; j++)
 				{
-					patterntracks[i*32+j] = bswapLE16(pmpd->data[j]);
+					patterntracks[i*32+j] = pmpd->data[j];
 				}
 			}
 			break;
@@ -303,7 +274,6 @@
 		case 0x5254:
 			if (dwTrackPos) break;
 			ntracks = *((WORD *)(lpStream+dwMemPos));
-			ntracks = bswapLE16(ntracks);
 			dwTrackPos = dwMemPos+2;
 			break;
 		// II: Instruments
@@ -322,7 +292,7 @@
 					INSTRUMENTHEADER *penv = Headers[nins];
 					memset(penv, 0, sizeof(INSTRUMENTHEADER));
 					memcpy(penv->name, lpStream+dwPos+2, 32);
-					penv->nGlobalVol = 128;
+					penv->nGlobalVol = 64;
 					penv->nPPC = 5*12;
 					for (j=0; j<lpStream[dwPos+1]; j++)
 					{
@@ -395,13 +365,9 @@
 				memcpy(m_szNames[nins], lpStream+dwPos+1, 32);
 				memcpy(pins->name, lpStream+dwPos+33, 8);
 				pins->nC4Speed = *((DWORD *)(lpStream+dwPos+41));
-				pins->nC4Speed = bswapLE32(pins->nC4Speed);
 				pins->nLength = *((DWORD *)(lpStream+dwPos+45));
-				pins->nLength = bswapLE32(pins->nLength);
 				pins->nLoopStart = *((DWORD *)(lpStream+dwPos+49));
-				pins->nLoopStart = bswapLE32(pins->nLoopStart);
 				pins->nLoopEnd = pins->nLoopStart + *((DWORD *)(lpStream+dwPos+53));
-				pins->nLoopEnd = bswapLE32(pins->nLoopEnd);
 				if (pins->nLoopEnd > pins->nLoopStart) pins->uFlags |= CHN_LOOP;
 				pins->nGlobalVol = 64;
 				if (lpStream[dwPos+58] & 0x01)
@@ -428,7 +394,6 @@
 				} else
 				{
 					DWORD dwLen = *((DWORD *)(lpStream+dwPos));
-					dwLen = bswapLE32(dwLen);
 					dwPos += 4;
 					if ((dwPos+dwLen <= dwMemLength) && (dwLen > 4))
 					{
@@ -466,23 +431,23 @@
 			for (UINT nve=0; nve<nvolenv; nve++, pve+=33) if (pve[0]+1 == insvolenv[iIns])
 			{
 				WORD vtick = 1;
-				penv->VolEnv.nNodes = 15;
+				penv->nVolEnv = 15;
 				for (UINT iv=0; iv<15; iv++)
 				{
 					if (iv) vtick += pve[iv*2+1];
-					penv->VolEnv.Ticks[iv] = vtick;
-					penv->VolEnv.Values[iv] = pve[iv*2+2];
+					penv->VolPoints[iv] = vtick;
+					penv->VolEnv[iv] = pve[iv*2+2];
 					if (!pve[iv*2+1])
 					{
-						penv->VolEnv.nNodes = iv+1;
+						penv->nVolEnv = iv+1;
 						break;
 					}
 				}
-				penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pve[31] & 0x0F;
+				penv->nVolSustainBegin = penv->nVolSustainEnd = pve[31] & 0x0F;
 				if (pve[31] & 0x10) penv->dwFlags |= ENV_VOLSUSTAIN;
 				if (pve[31] & 0x20) penv->dwFlags |= ENV_VOLLOOP;
-				penv->VolEnv.nLoopStart = pve[32] & 0x0F;
-				penv->VolEnv.nLoopEnd = pve[32] >> 4;
+				penv->nVolLoopStart = pve[32] & 0x0F;
+				penv->nVolLoopEnd = pve[32] >> 4;
 			}
 		}
 		// Setup panning envelope
@@ -492,22 +457,22 @@
 			for (UINT npe=0; npe<npanenv; npe++, ppe+=33) if (ppe[0]+1 == inspanenv[iIns])
 			{
 				WORD vtick = 1;
-				penv->PanEnv.nNodes = 15;
+				penv->nPanEnv = 15;
 				for (UINT iv=0; iv<15; iv++)
 				{
 					if (iv) vtick += ppe[iv*2+1];
-					penv->PanEnv.Ticks[iv] = vtick;
-					penv->PanEnv.Values[iv] = ppe[iv*2+2];
+					penv->PanPoints[iv] = vtick;
+					penv->PanEnv[iv] = ppe[iv*2+2];
 					if (!ppe[iv*2+1])
 					{
-						penv->PanEnv.nNodes = iv+1;
+						penv->nPanEnv = iv+1;
 						break;
 					}
 				}
 				if (ppe[31] & 0x10) penv->dwFlags |= ENV_PANSUSTAIN;
 				if (ppe[31] & 0x20) penv->dwFlags |= ENV_PANLOOP;
-				penv->PanEnv.nLoopStart = ppe[32] & 0x0F;
-				penv->PanEnv.nLoopEnd = ppe[32] >> 4;
+				penv->nPanLoopStart = ppe[32] & 0x0F;
+				penv->nPanLoopEnd = ppe[32] >> 4;
 			}
 		}
 	}
--- a/src/modplug/load_med.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_med.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -572,7 +572,6 @@
 	m_nChannels = 4;
 	m_nSamples = pmsh->numsamples;
 	if (m_nSamples > 63) m_nSamples = 63;
-	m_nStereoSeparation = ((pmsh2->mix_stereosep < 0) ? -32 : 32) * pmsh2->mix_stereosep;
 	// Tempo
 	m_nDefaultTempo = 125;
 	deftempo = bswapBE16(pmsh->deftempo);
@@ -812,7 +811,6 @@
 			if (!tracks) tracks = m_nChannels;
 			if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
 			PatternSize[iBlk] = lines;
-			PatternAllocSize[iBlk] = lines;
 			MODCOMMAND *p = Patterns[iBlk];
 			LPBYTE s = (LPBYTE)(lpStream + dwPos + 2);
 			UINT maxlen = tracks*lines*3;
@@ -849,7 +847,6 @@
 			if (!tracks) tracks = m_nChannels;
 			if ((Patterns[iBlk] = AllocatePattern(lines, m_nChannels)) == NULL) continue;
 			PatternSize[iBlk] = (WORD)lines;
-			PatternAllocSize[iBlk] = (WORD)lines;
 			DWORD dwBlockInfo = bswapBE32(pmb->info);
 			if ((dwBlockInfo) && (dwBlockInfo < dwMemLength - sizeof(MMD1BLOCKINFO)))
 			{
--- a/src/modplug/load_mod.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_mod.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -110,7 +110,7 @@
 	case CMD_PATTERNBREAK:		command = 0x0D; param = ((param / 10) << 4) | (param % 10); break;
 	case CMD_MODCMDEX:			command = 0x0E; break;
 	case CMD_SPEED:				command = 0x0F; if (param > 0x20) param = 0x20; break;
-	case CMD_TEMPO:				if (param > 0x20) { command = 0x0F; break; } return 0;
+	case CMD_TEMPO:				if (param > 0x20) { command = 0x0F; break; }
 	case CMD_GLOBALVOLUME:		command = 'G' - 55; break;
 	case CMD_GLOBALVOLSLIDE:	command = 'H' - 55; break;
 	case CMD_KEYOFF:			command = 'K' - 55; break;
@@ -192,7 +192,7 @@
 	 || (IsMagic(s, "M&K!")) || (IsMagic(s, "N.T."))) m_nChannels = 4; else
 	if ((IsMagic(s, "CD81")) || (IsMagic(s, "OKTA"))) m_nChannels = 8; else
 	if ((s[0]=='F') && (s[1]=='L') && (s[2]=='T') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else
-	if ((s[0]>='4') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else
+	if ((s[0]>='2') && (s[0]<='9') && (s[1]=='C') && (s[2]=='H') && (s[3]=='N')) m_nChannels = s[0] - '0'; else
 	if ((s[0]=='1') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 10; else
 	if ((s[0]=='2') && (s[1]>='0') && (s[1]<='9') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 20; else
 	if ((s[0]=='3') && (s[1]>='0') && (s[1]<='2') && (s[2]=='C') && (s[3]=='H')) m_nChannels = s[1] - '0' + 30; else
@@ -228,13 +228,19 @@
 		}
 		psmp->nLoopStart = loopstart;
 		psmp->nLoopEnd = loopstart + looplen;
-		if (psmp->nLength < 2) psmp->nLength = 0;
+		if (psmp->nLength < 4) psmp->nLength = 0;
 		if (psmp->nLength)
 		{
 			UINT derr = 0;
 			if (psmp->nLoopStart >= psmp->nLength) { psmp->nLoopStart = psmp->nLength-1; derr|=1; }
 			if (psmp->nLoopEnd > psmp->nLength) { psmp->nLoopEnd = psmp->nLength; derr |= 1; }
 			if (psmp->nLoopStart > psmp->nLoopEnd) derr |= 1;
+			if ((psmp->nLoopStart > psmp->nLoopEnd) || (psmp->nLoopEnd <= 8)
+			 || (psmp->nLoopEnd - psmp->nLoopStart <= 4))
+			{
+				psmp->nLoopStart = 0;
+				psmp->nLoopEnd = 0;
+			}
 			if (psmp->nLoopEnd > psmp->nLoopStart)
 			{
 				psmp->uFlags |= CHN_LOOP;
@@ -300,10 +306,11 @@
 	for (UINT ich=0; ich<m_nChannels; ich++)
 	{
 		ChnSettings[ich].nVolume = 64;
-		ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 256 : 0;
+		if (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN)
+			ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 256 : 0;
+		else
+			ChnSettings[ich].nPan = (((ich&3)==1) || ((ich&3)==2)) ? 0xC0 : 0x40;
 	}
-	m_nStereoSeparation = (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN) ? 128 : 64;
-	
 	// Reading channels
 	for (UINT ipat=0; ipat<nbp; ipat++)
 	{
@@ -311,7 +318,6 @@
 		{
 			if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break;
 			PatternSize[ipat] = 64;
-			PatternAllocSize[ipat] = 64;
 			if (dwMemPos + m_nChannels*256 >= dwMemLength) break;
 			MODCOMMAND *m = Patterns[ipat];
 			LPCBYTE p = lpStream + dwMemPos;
@@ -357,27 +363,22 @@
 
 
 #ifndef MODPLUG_NO_FILESAVE
+#pragma warning(disable:4100)
 
-#ifdef MSC_VER
-#pragma warning(disable:4100)
-#endif
-
-BOOL CSoundFile::SaveMod(diskwriter_driver_t *fp, UINT nPacking)
+BOOL CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking)
 //----------------------------------------------------------
 {
 	BYTE insmap[32];
 	UINT inslen[32];
 	BYTE bTab[32];
 	BYTE ord[128];
-	UINT chanlim;
+	FILE *f;
 
-	if ((!m_nChannels) || (!fp)) return FALSE;
-	chanlim  = GetHighestUsedChannel();
-	if (chanlim < 4) chanlim = 4;
-
+	if ((!m_nChannels) || (!lpszFileName)) return FALSE;
+	if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
 	memset(ord, 0, sizeof(ord));
 	memset(inslen, 0, sizeof(inslen));
-	if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+	if (m_nInstruments)
 	{
 		memset(insmap, 0, sizeof(insmap));
 		for (UINT i=1; i<32; i++) if (Headers[i])
@@ -393,28 +394,25 @@
 		for (UINT i=0; i<32; i++) insmap[i] = (BYTE)i;
 	}
 	// Writing song name
-	fp->o(fp, (const unsigned char *)m_szNames, 20);
+	fwrite(m_szNames, 20, 1, f);
 	// Writing instrument definition
 	for (UINT iins=1; iins<=31; iins++)
 	{
 		MODINSTRUMENT *pins = &Ins[insmap[iins]];
-		WORD gg;
-		FrequencyToTranspose(pins);
-
 		memcpy(bTab, m_szNames[iins],22);
 		inslen[iins] = pins->nLength;
 		if (inslen[iins] > 0x1fff0) inslen[iins] = 0x1fff0;
-		gg = bswapBE16(inslen[iins] / 2);
-		memcpy(bTab+22, &gg, 2);
+		bTab[22] = inslen[iins] >> 9;
+		bTab[23] = inslen[iins] >> 1;
 		if (pins->RelativeTone < 0) bTab[24] = 0x08; else
 		if (pins->RelativeTone > 0) bTab[24] = 0x07; else
 		bTab[24] = (BYTE)XM2MODFineTune(pins->nFineTune);
-		bTab[25] = pins->nVolume  / 4;
-		gg = bswapBE16(pins->nLoopStart / 2);
-		memcpy(bTab+26, &gg, 2);
-		gg = bswapBE16((pins->nLoopEnd - pins->nLoopStart)/ 2);
-		memcpy(bTab+28, &gg, 2);
-		fp->o(fp,(const unsigned char *) bTab, 30);
+		bTab[25] = pins->nVolume >> 2;
+		bTab[26] = pins->nLoopStart >> 9;
+		bTab[27] = pins->nLoopStart >> 1;
+		bTab[28] = (pins->nLoopEnd - pins->nLoopStart) >> 9;
+		bTab[29] = (pins->nLoopEnd - pins->nLoopStart) >> 1;
+		fwrite(bTab, 30, 1, f);
 	}
 	// Writing number of patterns
 	UINT nbp=0, norders=128;
@@ -429,27 +427,26 @@
 	}
 	bTab[0] = norders;
 	bTab[1] = m_nRestartPos;
-	fp->o(fp, (const unsigned char *)bTab, 2);
+	fwrite(bTab, 2, 1, f);
 	// Writing pattern list
 	if (norders) memcpy(ord, Order, norders);
-	fp->o(fp, (const unsigned char *)ord, 128);
+	fwrite(ord, 128, 1, f);
 	// Writing signature
-	if (chanlim == 4)
+	if (m_nChannels == 4)
 		lstrcpy((LPSTR)&bTab, "M.K.");
 	else
-		wsprintf((LPSTR)&bTab, "%uCHN", chanlim);
-	fp->o(fp, (const unsigned char *)bTab, 4);
+		wsprintf((LPSTR)&bTab, "%luCHN", m_nChannels);
+	fwrite(bTab, 4, 1, f);
 	// Writing patterns
 	for (UINT ipat=0; ipat<nbp; ipat++) if (Patterns[ipat])
 	{
 		BYTE s[64*4];
-		MODCOMMAND *pm = Patterns[ipat];
+		MODCOMMAND *m = Patterns[ipat];
 		for (UINT i=0; i<64; i++) if (i < PatternSize[ipat])
 		{
 			LPBYTE p=s;
-			for (UINT c=0; c<chanlim; c++,p+=4)
+			for (UINT c=0; c<m_nChannels; c++,p+=4,m++)
 			{
-				MODCOMMAND *m = &pm[ i * m_nChannels + c];
 				UINT param = ModSaveCommand(m, FALSE);
 				UINT command = param >> 8;
 				param &= 0xFF;
@@ -464,16 +461,16 @@
 					period = ProTrackerPeriodTable[period];
 				}
 				UINT instr = (m->instr > 31) ? 0 : m->instr;
-				p[0] = ((period / 256) & 0x0F) | (instr & 0x10);
-				p[1] = period % 256;
+				p[0] = ((period >> 8) & 0x0F) | (instr & 0x10);
+				p[1] = period & 0xFF;
 				p[2] = ((instr & 0x0F) << 4) | (command & 0x0F);
 				p[3] = param;
 			}
-			fp->o(fp, (const unsigned char *)s, chanlim*4);
+			fwrite(s, m_nChannels, 4, f);
 		} else
 		{
-			memset(s, 0, chanlim*4);
-			fp->o(fp, (const unsigned char *)s, chanlim*4);
+			memset(s, 0, m_nChannels*4);
+			fwrite(s, m_nChannels, 4, f);
 		}
 	}
 	// Writing instruments
@@ -486,18 +483,16 @@
 		{
 			if ((nPacking) && (CanPackSample((char *)pins->pSample, inslen[ismpd], nPacking)))
 			{
-				fp->o(fp, (const unsigned char *)"ADPCM", 5);
+				fwrite("ADPCM", 1, 5, f);
 				flags = RS_ADPCM4;
 			}
 		}
 #endif
-		WriteSample(fp, pins, flags, inslen[ismpd]);
+		WriteSample(f, pins, flags, inslen[ismpd]);
 	}
+	fclose(f);
 	return TRUE;
 }
 
-#ifdef MSC_VER
 #pragma warning(default:4100)
-#endif
-
 #endif // MODPLUG_NO_FILESAVE
--- a/src/modplug/load_mt2.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_mt2.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -282,7 +282,6 @@
 			Log("Pattern #%d @%04X: %d lines, %d bytes\n", iPat, dwMemPos-6, nLines, pmp->wDataLen);
 	#endif
 			PatternSize[iPat] = nLines;
-			PatternAllocSize[iPat] = nLines;
 			Patterns[iPat] = AllocatePattern(nLines, m_nChannels);
 			if (!Patterns[iPat]) return TRUE;
 			MODCOMMAND *m = Patterns[iPat];
@@ -396,7 +395,6 @@
 #endif
 	memset(InstrMap, 0, sizeof(InstrMap));
 	m_nInstruments = (pfh->wInstruments < MAX_INSTRUMENTS) ? pfh->wInstruments : MAX_INSTRUMENTS-1;
-	m_dwSongFlags |= SONG_INSTRUMENTMODE;
 	for (UINT iIns=1; iIns<=255; iIns++)
 	{
 		if (dwMemPos+36 > dwMemLength) return TRUE;
@@ -410,7 +408,7 @@
 			{
 				memset(penv, 0, sizeof(INSTRUMENTHEADER));
 				memcpy(penv->name, pmi->szName, 32);
-				penv->nGlobalVol = 128;
+				penv->nGlobalVol = 64;
 				penv->nPan = 128;
 				for (UINT i=0; i<120; i++)
 				{
@@ -462,7 +460,7 @@
 				for (UINT iEnv=0; iEnv<4; iEnv++) if (pehdr[iEnv])
 				{
 					MT2ENVELOPE *pme = pehdr[iEnv];
-					int *pEnvPoints = NULL;
+					WORD *pEnvPoints = NULL;
 					BYTE *pEnvData = NULL;
 				#ifdef MT2DEBUG
 					Log("  Env %d.%d @%04X: %d points\n", iIns, iEnv, (UINT)(((BYTE *)pme)-lpStream), pme->nPoints);
@@ -474,12 +472,12 @@
 						if (pme->nFlags & 1) penv->dwFlags |= ENV_VOLUME;
 						if (pme->nFlags & 2) penv->dwFlags |= ENV_VOLSUSTAIN;
 						if (pme->nFlags & 4) penv->dwFlags |= ENV_VOLLOOP;
-						penv->VolEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints;
-						penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = pme->nSustainPos;
-						penv->VolEnv.nLoopStart = pme->nLoopStart;
-						penv->VolEnv.nLoopEnd = pme->nLoopEnd;
-						pEnvPoints = penv->VolEnv.Ticks;
-						pEnvData = penv->VolEnv.Values;
+						penv->nVolEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
+						penv->nVolSustainBegin = penv->nVolSustainEnd = pme->nSustainPos;
+						penv->nVolLoopStart = pme->nLoopStart;
+						penv->nVolLoopEnd = pme->nLoopEnd;
+						pEnvPoints = penv->VolPoints;
+						pEnvData = penv->VolEnv;
 						break;
 
 					// Panning Envelope
@@ -487,12 +485,12 @@
 						if (pme->nFlags & 1) penv->dwFlags |= ENV_PANNING;
 						if (pme->nFlags & 2) penv->dwFlags |= ENV_PANSUSTAIN;
 						if (pme->nFlags & 4) penv->dwFlags |= ENV_PANLOOP;
-						penv->PanEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints;
-						penv->PanEnv.nSustainStart = penv->PanEnv.nSustainEnd = pme->nSustainPos;
-						penv->PanEnv.nLoopStart = pme->nLoopStart;
-						penv->PanEnv.nLoopEnd = pme->nLoopEnd;
-						pEnvPoints = penv->PanEnv.Ticks;
-						pEnvData = penv->PanEnv.Values;
+						penv->nPanEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
+						penv->nPanSustainBegin = penv->nPanSustainEnd = pme->nSustainPos;
+						penv->nPanLoopStart = pme->nLoopStart;
+						penv->nPanLoopEnd = pme->nLoopEnd;
+						pEnvPoints = penv->PanPoints;
+						pEnvData = penv->PanEnv;
 						break;
 
 					// Pitch/Filter envelope
@@ -500,12 +498,12 @@
 						if (pme->nFlags & 1) penv->dwFlags |= (iEnv==3) ? (ENV_PITCH|ENV_FILTER) : ENV_PITCH;
 						if (pme->nFlags & 2) penv->dwFlags |= ENV_PITCHSUSTAIN;
 						if (pme->nFlags & 4) penv->dwFlags |= ENV_PITCHLOOP;
-						penv->PitchEnv.nNodes = (pme->nPoints > 16) ? 16 : pme->nPoints;
-						penv->PitchEnv.nSustainStart = penv->PitchEnv.nSustainEnd = pme->nSustainPos;
-						penv->PitchEnv.nLoopStart = pme->nLoopStart;
-						penv->PitchEnv.nLoopEnd = pme->nLoopEnd;
-						pEnvPoints = penv->PitchEnv.Ticks;
-						pEnvData = penv->PitchEnv.Values;
+						penv->nPitchEnv = (pme->nPoints > 16) ? 16 : pme->nPoints;
+						penv->nPitchSustainBegin = penv->nPitchSustainEnd = pme->nSustainPos;
+						penv->nPitchLoopStart = pme->nLoopStart;
+						penv->nPitchLoopEnd = pme->nLoopEnd;
+						pEnvPoints = penv->PitchPoints;
+						pEnvData = penv->PitchEnv;
 					}
 					// Envelope data
 					if ((pEnvPoints) && (pEnvData) && (pedata[iEnv]))
@@ -594,7 +592,7 @@
 							Ins[nSmp].nVibType = pmi->bVibType;
 							Ins[nSmp].nVibSweep = pmi->bVibSweep;
 							Ins[nSmp].nVibDepth = pmi->bVibDepth;
-							Ins[nSmp].nVibRate = pmi->bVibRate/4;
+							Ins[nSmp].nVibRate = pmi->bVibRate;
 						}
 					}
 				}
--- a/src/modplug/load_mtm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_mtm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -59,8 +59,8 @@
 	 || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) return FALSE;
 	strncpy(m_szNames[0], pmh->songname, 20);
 	m_szNames[0][20] = 0;
-	if (dwMemPos + 37*pmh->numsamples + 128 + 192*bswapLE16(pmh->numtracks)
-	 + 64 * (pmh->lastpattern+1) + bswapLE16(pmh->commentsize) >= dwMemLength) return FALSE;
+	if (dwMemPos + 37*pmh->numsamples + 128 + 192*pmh->numtracks
+	 + 64 * (pmh->lastpattern+1) + pmh->commentsize >= dwMemLength) return FALSE;
 	m_nType = MOD_TYPE_MTM;
 	m_nSamples = pmh->numsamples;
 	m_nChannels = pmh->numchannels;
@@ -72,12 +72,12 @@
 		m_szNames[i][22] = 0;
 		Ins[i].nVolume = pms->volume << 2;
 		Ins[i].nGlobalVol = 64;
-		DWORD len = bswapLE32(pms->length);
+		DWORD len = pms->length;
 		if ((len > 4) && (len <= MAX_SAMPLE_LENGTH))
 		{
 			Ins[i].nLength = len;
-			Ins[i].nLoopStart = bswapLE32(pms->reppos);
-			Ins[i].nLoopEnd = bswapLE32(pms->repend);
+			Ins[i].nLoopStart = pms->reppos;
+			Ins[i].nLoopEnd = pms->repend;
 			if (Ins[i].nLoopEnd > Ins[i].nLength) Ins[i].nLoopEnd = Ins[i].nLength;
 			if (Ins[i].nLoopStart + 4 >= Ins[i].nLoopEnd) Ins[i].nLoopStart = Ins[i].nLoopEnd = 0;
 			if (Ins[i].nLoopEnd) Ins[i].uFlags |= CHN_LOOP;
@@ -104,14 +104,13 @@
 	dwMemPos += 128;
 	// Reading Patterns
 	LPCBYTE pTracks = lpStream + dwMemPos;
-	dwMemPos += 192 * bswapLE16(pmh->numtracks);
+	dwMemPos += 192 * pmh->numtracks;
 	LPWORD pSeq = (LPWORD)(lpStream + dwMemPos);
 	for (UINT pat=0; pat<=pmh->lastpattern; pat++)
 	{
 		PatternSize[pat] = 64;
-		PatternAllocSize[pat] = 64;
 		if ((Patterns[pat] = AllocatePattern(64, m_nChannels)) == NULL) break;
-		for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= bswapLE16(pmh->numtracks)) && (n < m_nChannels))
+		for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels))
 		{
 			LPCBYTE p = pTracks + 192 * (pSeq[n]-1);
 			MODCOMMAND *m = Patterns[pat] + n;
@@ -133,9 +132,9 @@
 		pSeq += 32;
 	}
 	dwMemPos += 64*(pmh->lastpattern+1);
-	if (bswapLE16(pmh->commentsize) && (dwMemPos + bswapLE16(pmh->commentsize) < dwMemLength))
+	if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength))
 	{
-		UINT n = bswapLE16(pmh->commentsize);
+		UINT n = pmh->commentsize;
 		m_lpszSongComments = new char[n+1];
 		if (m_lpszSongComments)
 		{
@@ -150,7 +149,7 @@
 			}
 		}
 	}
-	dwMemPos += bswapLE16(pmh->commentsize);
+	dwMemPos += pmh->commentsize;
 	// Reading Samples
 	for (UINT ismp=1; ismp<=m_nSamples; ismp++)
 	{
--- a/src/modplug/load_okt.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_okt.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -120,7 +120,6 @@
 			if ((Patterns[npat] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
 			MODCOMMAND *m = Patterns[npat];
 			PatternSize[npat] = rows;
-			PatternAllocSize[npat] = rows;
 			UINT imax = m_nChannels*rows;
 			for (UINT i=0; i<imax; i++, m++, dwPos+=4)
 			{
--- a/src/modplug/load_psm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_psm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -79,24 +79,27 @@
 //-----------------------------------------------------------
 {
 	PSMCHUNK *pfh = (PSMCHUNK *)lpStream;
+	PSMCHUNK pfh_swap;
 	DWORD dwMemPos, dwSongPos;
 	DWORD smpnames[MAX_SAMPLES];
 	DWORD patptrs[MAX_PATTERNS];
 	BYTE samplemap[MAX_SAMPLES];
 	UINT nPatterns;
 
+	pfh_swap.id = bswapLE32(pfh->id);
+	pfh_swap.len = bswapLE32(pfh->len);
+	pfh_swap.listid = bswapLE32(pfh->listid);
+
 	// Chunk0: "PSM ",filesize,"FILE"
 	if (dwMemLength < 256) return FALSE;
-	if (bswapLE32(pfh->id) == PSM_ID_OLD)
+	if (pfh_swap.id == PSM_ID_OLD)
 	{
 	#ifdef PSM_LOG
-		printf("Old PSM format not supported\n");
+		Log("Old PSM format not supported\n");
 	#endif
 		return FALSE;
 	}
-	if ((bswapLE32(pfh->id) != PSM_ID_NEW)
-	|| (bswapLE32(pfh->len)+12 > dwMemLength)
-	|| (bswapLE32(pfh->listid) != IFFID_FILE)) return FALSE;
+	if ((pfh_swap.id != PSM_ID_NEW) || (pfh_swap.len+12 > dwMemLength) || (pfh_swap.listid != IFFID_FILE)) return FALSE;
 	m_nType = MOD_TYPE_PSM;
 	m_nChannels = 16;
 	m_nSamples = 0;
@@ -108,16 +111,19 @@
 		UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40;
 		ChnSettings[iChPan].nPan = pan;
 	}
-	m_szNames[0][0]=0;
 	while (dwMemPos+8 < dwMemLength)
 	{
 		PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
-		if ((bswapLE32(pchunk->len) >= dwMemLength - 8)
-		|| (dwMemPos + bswapLE32(pchunk->len) + 8 > dwMemLength)) break;
+
+		pchunk->id = bswapLE32(pchunk->id);
+		pchunk->len = bswapLE32(pchunk->len);
+		pchunk->listid = bswapLE32(pchunk->listid);
+
+		if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break;
 		dwMemPos += 8;
 		PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
-		ULONG len = bswapLE32(pchunk->len);
-		if (len) switch(bswapLE32(pchunk->id))
+		ULONG len = pchunk->len;
+		if (len) switch(pchunk->id)
 		{
 		// "TITL": Song title
 		case IFFID_TITL:
@@ -146,16 +152,23 @@
 				m_nSamples++;
 				MODINSTRUMENT *pins = &Ins[m_nSamples];
 				PSMSAMPLE *psmp = (PSMSAMPLE *)pdata;
-				smpnames[m_nSamples] = bswapLE32(psmp->smpid);
+
+				psmp->smpid = bswapLE32(psmp->smpid);
+				psmp->length = bswapLE32(psmp->length);
+				psmp->loopstart = bswapLE32(psmp->loopstart); 
+				psmp->loopend = bswapLE32(psmp->loopend);
+				psmp->samplerate = bswapLE32(psmp->samplerate);
+
+				smpnames[m_nSamples] = psmp->smpid;
 				memcpy(m_szNames[m_nSamples], psmp->samplename, 31);
 				m_szNames[m_nSamples][31] = 0;
 				samplemap[m_nSamples-1] = (BYTE)m_nSamples;
 				// Init sample
 				pins->nGlobalVol = 0x40;
-				pins->nC4Speed = bswapLE32(psmp->samplerate);
-				pins->nLength = bswapLE32(psmp->length);
-				pins->nLoopStart = bswapLE32(psmp->loopstart);
-				pins->nLoopEnd = bswapLE32(psmp->loopend);
+				pins->nC4Speed = psmp->samplerate;
+				pins->nLength = psmp->length;
+				pins->nLoopStart = psmp->loopstart;
+				pins->nLoopEnd = psmp->loopend;
 				pins->nPan = 128;
 				pins->nVolume = (psmp->defvol+1) * 2;
 				pins->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0;
@@ -184,7 +197,7 @@
 			}
 	#endif
 		}
-		dwMemPos += bswapLE32(pchunk->len);
+		dwMemPos += pchunk->len;
 	}
 	// Step #1: convert song structure
 	PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8);
@@ -197,12 +210,16 @@
 		while (dwMemPos + 8 < dwSongEnd)
 		{
 			PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
+
+			pchunk->id = bswapLE32(pchunk->id);
+			pchunk->len = bswapLE32(pchunk->len);
+			pchunk->listid = bswapLE32(pchunk->listid);
+
 			dwMemPos += 8;
-			if ((bswapLE32(pchunk->len) > dwSongEnd)
-			|| (dwMemPos + bswapLE32(pchunk->len) > dwSongEnd)) break;
+			if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break;
 			PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
-			ULONG len = bswapLE32(pchunk->len);
-			switch(bswapLE32(pchunk->id))
+			ULONG len = pchunk->len;
+			switch(pchunk->id)
 			{
 			case IFFID_OPLH:
 				if (len >= 0x20)
@@ -248,7 +265,7 @@
 				}
 				break;
 			}
-			dwMemPos += bswapLE32(pchunk->len);
+			dwMemPos += pchunk->len;
 		}
 	}
 
@@ -256,66 +273,85 @@
 	for (UINT nPat=0; nPat<nPatterns; nPat++)
 	{
 		PSMPATTERN *pPsmPat = (PSMPATTERN *)(lpStream+patptrs[nPat]+8);
-		ULONG len = bswapLE32(*(DWORD *)(lpStream+patptrs[nPat]+4)) - 12;
-		UINT nRows = bswapLE16(pPsmPat->rows);
-		if (len > bswapLE32(pPsmPat->size)) len = bswapLE32(pPsmPat->size);
+
+		pPsmPat->size = bswapLE32(pPsmPat->size);
+		pPsmPat->name = bswapLE32(pPsmPat->name);
+		pPsmPat->rows = bswapLE16(pPsmPat->rows);
+
+		ULONG len = *(DWORD *)(lpStream+patptrs[nPat]+4) - 12;
+		UINT nRows = pPsmPat->rows;
+		if (len > pPsmPat->size) len = pPsmPat->size;
 		if ((nRows < 64) || (nRows > 256)) nRows = 64;
 		PatternSize[nPat] = nRows;
-		PatternAllocSize[nPat] = nRows;
 		if ((Patterns[nPat] = AllocatePattern(nRows, m_nChannels)) == NULL) break;
 		MODCOMMAND *m = Patterns[nPat];
-		MODCOMMAND *sp, dummy;
 		BYTE *p = pPsmPat->data;
 		UINT pos = 0;
 		UINT row = 0;
-		UINT rowlim;
+		UINT oldch = 0;
+		BOOL bNewRow = FALSE;
 	#ifdef PSM_LOG
-		//printf("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream));
+		Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream));
 	#endif
-		rowlim = bswapLE16(pPsmPat->reserved1)-2;
 		while ((row < nRows) && (pos+1 < len))
 		{
-			UINT flags, ch;
-			if ((pos+1) >= rowlim) {
-				pos = rowlim;
-				rowlim = (((int)p[pos+1])<<8)
-					| ((int)p[pos+0]);
-				m += m_nChannels;
-				row++;
-				rowlim += pos;
-				pos += 2;
+			UINT flags = p[pos++];
+			UINT ch = p[pos++];
+			
+		#ifdef PSM_LOG
+			//Log("flags+ch: %02X.%02X\n", flags, ch);
+		#endif
+			if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/)
+			{
+				if ((pos+1<len) && (!(p[pos] & 0x0f)) && (p[pos+1] < m_nChannels))
+				{
+				#ifdef PSM_LOG
+					//if (!nPat) Log("Continuing on new row\n");
+				#endif
+					row++;
+					m += m_nChannels;
+					oldch = ch;
+					continue;
+				}
 			}
-			flags = p[pos++];
-			ch = p[pos++];
-			if (ch >= m_nChannels) {
+			if ((pos >= len) || (row >= nRows)) break;
+			if (!(flags & 0xf0))
+			{
 			#ifdef PSM_LOG
-				printf("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch);
+				//if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]);
 			#endif
-				sp = &dummy;
-			} else {
-				sp = &m[ch];
+				row++;
+				m += m_nChannels;
+				bNewRow = TRUE;
+				oldch = ch;
+				continue;
+			}
+			bNewRow = FALSE;
+			if (ch >= m_nChannels)
+			{
+			#ifdef PSM_LOG
+				if (!nPat) Log("Invalid channel row=%d (0x%02X.0x%02X)\n", row, flags, ch);
+			#endif
+				ch = 0;
 			}
 			// Note + Instr
-			if ((flags & 0x80) && (pos+1 < len))
+			if ((flags & 0x40) && (pos+1 < len))
 			{
 				UINT note = p[pos++];
-				note = (note>>4)*12+(note&0x0f)+12+1;
-				if (note > 0x80) note = 0;
-				sp->note = note;
-			}
-			if ((flags & 0x40) && (pos+1 < len))
-			{
 				UINT nins = p[pos++];
 			#ifdef PSM_LOG
-				if ((!nPat) && (nins >= m_nSamples)) printf("WARNING: invalid instrument number (%d)\n", nins);
+				//if (!nPat) Log("note+ins: %02X.%02X\n", note, nins);
+				if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins);
 			#endif
-				sp->instr = samplemap[nins];
+				if ((note) && (note < 0x80)) note = (note>>4)*12+(note&0x0f)+12+1;
+				m[ch].instr = samplemap[nins];
+				m[ch].note = note;
 			}
 			// Volume
 			if ((flags & 0x20) && (pos < len))
 			{
-				sp->volcmd = VOLCMD_VOLUME;
-				sp->vol = p[pos++] / 2;
+				m[ch].volcmd = VOLCMD_VOLUME;
+				m[ch].vol = p[pos++] / 2;
 			}
 			// Effect
 			if ((flags & 0x10) && (pos+1 < len))
@@ -323,94 +359,40 @@
 				UINT command = p[pos++];
 				UINT param = p[pos++];
 				// Convert effects
-				switch(command & 0x3F)
+				switch(command)
 				{
 				// 01: fine volslide up
-				case 0x01:
-#if PSM_LOG
-					printf("fvup command pat=%d row=%d ch=%d   %02x %02x\n",
-							nPat,
-								row,1+ch,
-								command, param);
-#endif
-#if 0
-					if (!sp->volcmd) {
-						sp->volcmd = VOLCMD_FINEVOLUP;
-						sp->vol = (param >> 1) & 0xF;
-						command = CMD_PORTAMENTOUP;
-						param>>=4; param |= 0xf0;
-						if (param == 240) param=241;
-					} else {
-#endif
-					command = CMD_VOLUMESLIDE;
-					param |= 0x0f;
-					if (param == 15) param=31;
-					break;
-				// 02: volslide up
-				case 0x02:	command = CMD_VOLUMESLIDE; param>>=1; param<<=4; break;
-				// 03: fine volslide down
-				case 0x03:	
-#if PSM_LOG
-					printf("fvdown command pat=%d row=%d ch=%d   %02x %02x\n",
-							nPat,
-								row,1+ch,
-								command, param);
-#endif
-#if 0
-					if (!sp->volcmd) {
-						sp->volcmd = VOLCMD_FINEVOLDOWN;
-						sp->vol = (param >> 2) & 0xF;
-						if (!sp->vol) sp->vol = 1;
-						command = CMD_PORTAMENTODOWN;
-					}
-#endif
-					command = CMD_VOLUMESLIDE;
-					param>>=4; param |= 0xf0;
-					if (param == 240) param=241;
-					break;
-				// 04: volslide down
-				case 0x04:	command = CMD_VOLUMESLIDE; param>>=1; break;
+				case 0x01:	command = CMD_VOLUMESLIDE; param |= 0x0f; break;
+				// 04: fine volslide down
+				case 0x04:	command = CMD_VOLUMESLIDE; param>>=4; param |= 0xf0; break;
 				// 0C: portamento up
 				case 0x0C:	command = CMD_PORTAMENTOUP; param = (param+1)/2; break;
 				// 0E: portamento down
 				case 0x0E:	command = CMD_PORTAMENTODOWN; param = (param+1)/2; break;
-				// 0F: tone portamento
-				case 0x0F:	command = CMD_TONEPORTAMENTO; param = param/4; break;
-				// 15: vibrato
-				case 0x15:	command = CMD_VIBRATO; break;
-				// 29: wtf
-				case 0x29: pos += 2; break;
-				// 2A: retrig
-				case 0x2A:	command = CMD_RETRIG; break;
 				// 33: Position Jump
 				case 0x33:	command = CMD_POSITIONJUMP; break;
 				// 34: Pattern break
 				case 0x34:	command = CMD_PATTERNBREAK; break;
 				// 3D: speed
-				case 0x3D:	command = CMD_SPEED;
-						if (!row && !nPat)
-							m_nDefaultSpeed = param;
-						break;
+				case 0x3D:	command = CMD_SPEED; break;
 				// 3E: tempo
-				case 0x3E:	command = CMD_TEMPO;
-						if (!row && !nPat)
-							m_nDefaultTempo = param;
-						break;
+				case 0x3E:	command = CMD_TEMPO; break;
 				// Unknown
 				default:
 				#ifdef PSM_LOG
-					printf("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param);
+					Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param);
 				#endif
 					command = param = 0;
 				}
-				sp->command = (BYTE)command;
-				sp->param = (BYTE)param;
+				m[ch].command = (BYTE)command;
+				m[ch].param = (BYTE)param;
 			}
+			oldch = ch;
 		}
 	#ifdef PSM_LOG
 		if (pos < len)
 		{
-//			printf("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos);
+			Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos);
 		}
 	#endif
 	}
--- a/src/modplug/load_ptm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_ptm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -115,10 +115,10 @@
 		{
 			UINT smpflg = RS_PCM8D;
 			DWORD samplepos;
-			pins->nLength = bswapLE32(*psmp->length);
-			pins->nLoopStart = bswapLE32(*psmp->loopbeg);
-			pins->nLoopEnd = bswapLE32(*psmp->loopend);
-			samplepos = bswapLE32(*psmp->fileofs);
+			pins->nLength = bswapLE32(*(LPDWORD)(psmp->length));
+			pins->nLoopStart = bswapLE32(*(LPDWORD)(psmp->loopbeg));
+			pins->nLoopEnd = bswapLE32(*(LPDWORD)(psmp->loopend));
+			samplepos = bswapLE32(*(LPDWORD)(&psmp->fileofs));
 			if (psmp->sampletype & 4) pins->uFlags |= CHN_LOOP;
 			if (psmp->sampletype & 8) pins->uFlags |= CHN_PINGPONGLOOP;
 			if (psmp->sampletype & 16)
@@ -141,7 +141,6 @@
 		dwMemPos = ((UINT)pfh.patseg[ipat]) << 4;
 		if ((!dwMemPos) || (dwMemPos >= dwMemLength)) continue;
 		PatternSize[ipat] = 64;
-		PatternAllocSize[ipat] = 64;
 		if ((Patterns[ipat] = AllocatePattern(64, m_nChannels)) == NULL) break;
 		//
 		MODCOMMAND *m = Patterns[ipat];
--- a/src/modplug/load_s3m.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_s3m.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -289,14 +289,14 @@
 		{
 			UINT j = bswapLE32(*((LPDWORD)(s+0x10)));
 			if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH;
-			if (j < 2) j = 0;
+			if (j < 4) j = 0;
 			Ins[iSmp].nLength = j;
 			j = bswapLE32(*((LPDWORD)(s+0x14)));
 			if (j >= Ins[iSmp].nLength) j = Ins[iSmp].nLength - 1;
 			Ins[iSmp].nLoopStart = j;
 			j = bswapLE32(*((LPDWORD)(s+0x18)));
 			if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH;
-			if (j < 2) j = 0;
+			if (j < 4) j = 0;
 			if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength;
 			Ins[iSmp].nLoopEnd = j;
 			j = s[0x1C];
@@ -319,15 +319,11 @@
 	// Reading patterns
 	for (UINT iPat=0; iPat<patnum; iPat++)
 	{
-                UINT nInd = ((DWORD)ptr[nins+iPat]) << 4;
-                // if the parapointer is zero, the pattern is blank (so ignore it)
-                if (nInd == 0)
-                        continue;
-                if (nInd + 0x40 > dwMemLength) continue;
+		UINT nInd = ((DWORD)ptr[nins+iPat]) << 4;
+		if (nInd + 0x40 > dwMemLength) continue;
 		WORD len = bswapLE16(*((WORD *)(lpStream+nInd)));
 		nInd += 2;
 		PatternSize[iPat] = 64;
-		PatternAllocSize[iPat] = 64;
 		if ((!len) || (nInd + len > dwMemLength - 6)
 		 || ((Patterns[iPat] = AllocatePattern(64, m_nChannels)) == NULL)) continue;
 		LPBYTE src = (LPBYTE)(lpStream+nInd);
@@ -387,11 +383,8 @@
 	// Reading samples
 	for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw]))
 	{
-		UINT flags;
-		if (insflags[iRaw-1] & 4)
-			flags = (psfh.version == 1) ? RS_PCM16S : RS_PCM16U;
-		else
-			flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U;
+		UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U;
+		if (insflags[iRaw-1] & 4) flags += 5;
 		if (insflags[iRaw-1] & 2) flags |= RSF_STEREO;
 		if (inspack[iRaw-1] == 4) flags = RS_ADPCM4;
 		dwMemPos = insfile[iRaw];
@@ -405,10 +398,7 @@
 
 
 #ifndef MODPLUG_NO_FILESAVE
-
-#ifdef MSC_VER
 #pragma warning(disable:4100)
-#endif
 
 static BYTE S3MFiller[16] =
 {
@@ -417,18 +407,19 @@
 };
 
 
-BOOL CSoundFile::SaveS3M(diskwriter_driver_t *fp, UINT nPacking)
+BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking)
 //----------------------------------------------------------
 {
+	FILE *f;
 	BYTE header[0x60];
 	UINT nbo,nbi,nbp,i;
-	UINT chanlim;
 	WORD patptr[128];
 	WORD insptr[128];
 	BYTE buffer[5*1024];
 	S3MSAMPLESTRUCT insex[128];
 
-	if ((!m_nChannels) || (!fp)) return FALSE;
+	if ((!m_nChannels) || (!lpszFileName)) return FALSE;
+	if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
 	// Writing S3M header
 	memset(header, 0, sizeof(header));
 	memset(insex, 0, sizeof(insex));
@@ -436,14 +427,12 @@
 	header[0x1B] = 0;
 	header[0x1C] = 0x1A;
 	header[0x1D] = 0x10;
-        nbo = (GetNumPatterns());
-        if (nbo == 0)
-                nbo = 2;
-        else if (nbo & 1)
-                nbo++;
-        header[0x20] = nbo & 0xFF;
+	nbo = (GetNumPatterns() + 15) & 0xF0;
+	if (!nbo) nbo = 16;
+	header[0x20] = nbo & 0xFF;
 	header[0x21] = nbo >> 8;
-	nbi = m_nSamples;
+	nbi = m_nInstruments;
+	if (!nbi) nbi = m_nSamples;
 	if (nbi > 99) nbi = 99;
 	header[0x22] = nbi & 0xFF;
 	header[0x23] = nbi >> 8;
@@ -467,67 +456,55 @@
 	header[0x32] = m_nDefaultTempo;
 	header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80;	// Stereo
 	header[0x35] = 0xFC;
-
-	chanlim = GetHighestUsedChannel()+1;
-	if (chanlim < 4) chanlim = 4;
-	if (chanlim > 32) chanlim = 32;
-
 	for (i=0; i<32; i++)
 	{
-		if (i < chanlim)
+		if (i < m_nChannels)
 		{
 			UINT tmp = (i & 0x0F) >> 1;
 			header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp);
 		} else header[0x40+i] = 0xFF;
 	}
-	fp->o(fp, (const unsigned char *)header, 0x60);
-	fp->o(fp, (const unsigned char *)Order, nbo);
+	fwrite(header, 0x60, 1, f);
+	fwrite(Order, nbo, 1, f);
 	memset(patptr, 0, sizeof(patptr));
 	memset(insptr, 0, sizeof(insptr));
 	UINT ofs0 = 0x60 + nbo;
-	UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0);
+	UINT ofs1 = ((0x60 + nbo + nbi*2 + nbp*2 + 15) & 0xFFF0) + 0x20;
 	UINT ofs = ofs1;
-	if (header[0x35] == 0xFC) {
-		ofs += 0x20;
-		ofs1 += 0x20;
-	}
 
-	for (i=0; i<nbi; i++) insptr[i] = bswapLE16((WORD)((ofs + i*0x50) / 16));
-	for (i=0; i<nbp; i++) patptr[i] = bswapLE16((WORD)((ofs + nbi*0x50) / 16));
-	fp->o(fp, (const unsigned char *)insptr, nbi*2);
-	fp->o(fp, (const unsigned char *)patptr, nbp*2);
+	for (i=0; i<nbi; i++) insptr[i] = (WORD)((ofs + i*0x50) / 16);
+	for (i=0; i<nbp; i++) patptr[i] = (WORD)((ofs + nbi*0x50) / 16);
+	fwrite(insptr, nbi, 2, f);
+	fwrite(patptr, nbp, 2, f);
 	if (header[0x35] == 0xFC)
 	{
 		BYTE chnpan[32];
 		for (i=0; i<32; i++)
 		{
-			UINT nPan = ((ChnSettings[i].nPan+7) < 0xF0) ? ChnSettings[i].nPan+7 : 0xF0;
-			chnpan[i] = (i<chanlim) ? 0x20 | (nPan >> 4) : 0x08;
+			chnpan[i] = 0x20 | (ChnSettings[i].nPan >> 4);
 		}
-		fp->o(fp, (const unsigned char *)chnpan, 0x20);
+		fwrite(chnpan, 0x20, 1, f);
 	}
 	if ((nbi*2+nbp*2) & 0x0F)
 	{
-		fp->o(fp, (const unsigned char *)S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F));
+		fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f);
 	}
-	fp->l(fp, ofs1);
-	ofs1 = fp->pos;
-	fp->o(fp, (const unsigned char *)insex, nbi*0x50);
+	ofs1 = ftell(f);
+	fwrite(insex, nbi, 0x50, f);
 	// Packing patterns
 	ofs += nbi*0x50;
-	fp->l(fp,ofs);
 	for (i=0; i<nbp; i++)
 	{
 		WORD len = 64;
 		memset(buffer, 0, sizeof(buffer));
-		patptr[i] = bswapLE16(ofs / 16);
+		patptr[i] = ofs / 16;
 		if (Patterns[i])
 		{
 			len = 2;
 			MODCOMMAND *p = Patterns[i];
 			for (int row=0; row<64; row++) if (row < PatternSize[i])
 			{
-				for (UINT j=0; j < 32 && j<chanlim; j++)
+				for (UINT j=0; j<m_nChannels; j++)
 				{
 					UINT b = j;
 					MODCOMMAND *m = &p[row*m_nChannels+j];
@@ -536,19 +513,8 @@
 					UINT vol = m->vol;
 					UINT command = m->command;
 					UINT param = m->param;
-					UINT inst = m->instr;
 
-					if (m_dwSongFlags & SONG_INSTRUMENTMODE
-					&& note && inst) {
-						UINT nn = Headers[inst]->Keyboard[note];
-						UINT nm = Headers[inst]->NoteMap[note];
-						/* translate on save */
-						note = nm;
-						inst = nn;
-					}
-
-
-					if ((note) || (inst)) b |= 0x20;
+					if ((note) || (m->instr)) b |= 0x20;
 					if (!note) note = 0xFF; else
 					if (note >= 0xFE) note = 0xFE; else
 					if (note < 13) note = 0; else note -= 13;
@@ -573,7 +539,7 @@
 						if (b & 0x20)
 						{
 							buffer[len++] = note;
-							buffer[len++] = inst;
+							buffer[len++] = m->instr;
 						}
 						if (b & 0x40)
 						{
@@ -594,31 +560,46 @@
 		buffer[0] = (len - 2) & 0xFF;
 		buffer[1] = (len - 2) >> 8;
 		len = (len+15) & (~0x0F);
-		
-		fp->o(fp, (const unsigned char *)buffer, len);
+		fwrite(buffer, len, 1, f);
 		ofs += len;
 	}
 	// Writing samples
 	for (i=1; i<=nbi; i++)
 	{
 		MODINSTRUMENT *pins = &Ins[i];
+		if (m_nInstruments)
+		{
+			pins = Ins;
+			if (Headers[i])
+			{
+				for (UINT j=0; j<128; j++)
+				{
+					UINT n = Headers[i]->Keyboard[j];
+					if ((n) && (n < MAX_INSTRUMENTS))
+					{
+						pins = &Ins[n];
+						break;
+					}
+				}
+			}
+		}
 		memcpy(insex[i-1].dosname, pins->name, 12);
 		memcpy(insex[i-1].name, m_szNames[i], 28);
 		memcpy(insex[i-1].scrs, "SCRS", 4);
 		insex[i-1].hmem = (BYTE)((DWORD)ofs >> 20);
-		insex[i-1].memseg = bswapLE16((WORD)((DWORD)ofs >> 4));
+		insex[i-1].memseg = (WORD)((DWORD)ofs >> 4);
 		if (pins->pSample)
 		{
 			insex[i-1].type = 1;
-			insex[i-1].length = bswapLE32(pins->nLength);
-			insex[i-1].loopbegin = bswapLE32(pins->nLoopStart);
-			insex[i-1].loopend = bswapLE32(pins->nLoopEnd);
+			insex[i-1].length = pins->nLength;
+			insex[i-1].loopbegin = pins->nLoopStart;
+			insex[i-1].loopend = pins->nLoopEnd;
 			insex[i-1].vol = pins->nVolume / 4;
 			insex[i-1].flags = (pins->uFlags & CHN_LOOP) ? 1 : 0;
 			if (pins->nC4Speed)
-				insex[i-1].finetune = bswapLE32(pins->nC4Speed);
+				insex[i-1].finetune = pins->nC4Speed;
 			else
-				insex[i-1].finetune = bswapLE32(TransposeToFrequency(pins->RelativeTone, pins->nFineTune));
+				insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune);
 			UINT flags = RS_PCM8U;
 #ifndef NO_PACKING
 			if (nPacking)
@@ -643,28 +624,27 @@
 					flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U;
 				}
 			}
-			DWORD len = WriteSample(fp, pins, flags);
+			DWORD len = WriteSample(f, pins, flags);
 			if (len & 0x0F)
 			{
-				fp->o(fp, (const unsigned char *)S3MFiller, 0x10 - (len & 0x0F));
+				fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f);
 			}
 			ofs += (len + 15) & (~0x0F);
-		} else {
+		} else
+		{
 			insex[i-1].length = 0;
 		}
 	}
 	// Updating parapointers
-	fp->l(fp, ofs0);
-	fp->o(fp, (const unsigned char *)insptr, nbi*2);
-	fp->o(fp, (const unsigned char *)patptr, nbp*2);
-	fp->l(fp, ofs1);
-	fp->o(fp, (const unsigned char *)insex, 0x50*nbi);
+	fseek(f, ofs0, SEEK_SET);
+	fwrite(insptr, nbi, 2, f);
+	fwrite(patptr, nbp, 2, f);
+	fseek(f, ofs1, SEEK_SET);
+	fwrite(insex, 0x50, nbi, f);
+	fclose(f);
 	return TRUE;
 }
 
-#ifdef MSC_VER
 #pragma warning(default:4100)
-#endif
-
 #endif // MODPLUG_NO_FILESAVE
 
--- a/src/modplug/load_stm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_stm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -94,14 +94,14 @@
 		STMSAMPLE *pStm = &phdr->sample[nIns];  // STM sample data
 		memcpy(pIns->name, pStm->filename, 13);
 		memcpy(m_szNames[nIns+1], pStm->filename, 12);
-		pIns->nC4Speed = pStm->c2spd;
+		pIns->nC4Speed = bswapLE16(pStm->c2spd);
 		pIns->nGlobalVol = 64;
 		pIns->nVolume = pStm->volume << 2;
 		if (pIns->nVolume > 256) pIns->nVolume = 256;
-		pIns->nLength = pStm->length;
-		if ((pIns->nLength < 2) || (!pIns->nVolume)) pIns->nLength = 0;
-		pIns->nLoopStart = pStm->loopbeg;
-		pIns->nLoopEnd = pStm->loopend;
+		pIns->nLength = bswapLE16(pStm->length);
+		if ((pIns->nLength < 4) || (!pIns->nVolume)) pIns->nLength = 0;
+		pIns->nLoopStart = bswapLE16(pStm->loopbeg);
+		pIns->nLoopEnd = bswapLE16(pStm->loopend);
 		if ((pIns->nLoopEnd > pIns->nLoopStart) && (pIns->nLoopEnd != 0xFFFF)) pIns->uFlags |= CHN_LOOP;
 	}
 	dwMemPos = sizeof(STMHEADER);
@@ -111,7 +111,6 @@
 	{
 		if (dwMemPos + 64*4*4 > dwMemLength) return TRUE;
 		PatternSize[nPat] = 64;
-		PatternAllocSize[nPat] = 64;
 		if ((Patterns[nPat] = AllocatePattern(64, m_nChannels)) == NULL) return TRUE;
 		MODCOMMAND *m = Patterns[nPat];
 		STMNOTE *p = (STMNOTE *)(lpStream + dwMemPos);
--- a/src/modplug/load_ult.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_ult.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -135,7 +135,6 @@
 		if (nAllocPat < MAX_PATTERNS)
 		{
 			PatternSize[nAllocPat] = 64;
-			PatternAllocSize[nAllocPat] = 64;
 			Patterns[nAllocPat] = AllocatePattern(64, m_nChannels);
 		}
 	}
--- a/src/modplug/load_wav.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_wav.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -18,53 +18,26 @@
 //---------------------------------------------------------------
 {
 	DWORD dwMemPos = 0;
-	WAVEFILEHEADER phdr;
-	WAVEFORMATHEADER pfmt;
-
-	if ((!lpStream)
-	|| (dwMemLength < (DWORD)(sizeof(WAVEFORMATHEADER)+sizeof(WAVEFILEHEADER))))
-		return FALSE;
-
-	memcpy(&phdr, lpStream, sizeof(phdr));
-	memcpy(&pfmt, lpStream+sizeof(phdr), sizeof(pfmt));
-
-	phdr.id_RIFF = bswapLE32(phdr.id_RIFF);
-	phdr.filesize = bswapLE32(phdr.filesize);
-	phdr.id_WAVE = bswapLE32(phdr.id_WAVE);
-
-	pfmt.id_fmt = bswapLE32(pfmt.id_fmt);
-	pfmt.hdrlen = bswapLE32(pfmt.hdrlen);
-	pfmt.format = bswapLE16(pfmt.format);
-	pfmt.channels = bswapLE16(pfmt.channels);
-	pfmt.freqHz = bswapLE32(pfmt.freqHz);
-	pfmt.bytessec = bswapLE32(pfmt.bytessec);
-	pfmt.samplesize = bswapLE16(pfmt.samplesize);
-	pfmt.bitspersample = bswapLE16(pfmt.bitspersample);
-
-	if ((phdr.id_RIFF != IFFID_RIFF) || (phdr.id_WAVE != IFFID_WAVE)
-	 || (pfmt.id_fmt != IFFID_fmt)) return FALSE;
-
-	dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt.hdrlen;
-
+	WAVEFILEHEADER *phdr = (WAVEFILEHEADER *)lpStream;
+	WAVEFORMATHEADER *pfmt = (WAVEFORMATHEADER *)(lpStream + sizeof(WAVEFILEHEADER));
+	if ((!lpStream) || (dwMemLength < (DWORD)sizeof(WAVEFILEHEADER))) return FALSE;
+	if ((phdr->id_RIFF != IFFID_RIFF) || (phdr->id_WAVE != IFFID_WAVE)
+	 || (pfmt->id_fmt != IFFID_fmt)) return FALSE;
+	dwMemPos = sizeof(WAVEFILEHEADER) + 8 + pfmt->hdrlen;
 	if ((dwMemPos + 8 >= dwMemLength)
-	 || ((pfmt.format != WAVE_FORMAT_PCM) && (pfmt.format != WAVE_FORMAT_EXTENSIBLE))
-	 || (pfmt.channels > 4)
-	 || (!pfmt.channels)
-	 || (!pfmt.freqHz)
-	 || (pfmt.bitspersample & 7)
-	 || (pfmt.bitspersample < 8)
-	 || (pfmt.bitspersample > 32))  return FALSE;
-
-	WAVEDATAHEADER pdata;
-
+	 || ((pfmt->format != WAVE_FORMAT_PCM) && (pfmt->format != WAVE_FORMAT_EXTENSIBLE))
+	 || (pfmt->channels > 4)
+	 || (!pfmt->channels)
+	 || (!pfmt->freqHz)
+	 || (pfmt->bitspersample & 7)
+	 || (pfmt->bitspersample < 8)
+	 || (pfmt->bitspersample > 32))  return FALSE;
+	WAVEDATAHEADER *pdata;
 	for (;;)
 	{
-		memcpy(&pdata, lpStream+dwMemPos, sizeof(pdata));
-		pdata.id_data = bswapLE32(pdata.id_data);
-		pdata.length = bswapLE32(pdata.length);
-
-		if (pdata.id_data == IFFID_data) break;
-		dwMemPos += pdata.length + 8;
+		pdata = (WAVEDATAHEADER *)(lpStream + dwMemPos);
+		if (pdata->id_data == IFFID_data) break;
+		dwMemPos += pdata->length + 8;
 		if (dwMemPos + 8 >= dwMemLength) return FALSE;
 	}
 	m_nType = MOD_TYPE_WAV;
@@ -77,19 +50,18 @@
 	Order[0] = 0;
 	Order[1] = 0xFF;
 	PatternSize[0] = PatternSize[1] = 64;
-	PatternAllocSize[0] = PatternAllocSize[1] = 64;
 	if ((Patterns[0] = AllocatePattern(64, 4)) == NULL) return TRUE;
 	if ((Patterns[1] = AllocatePattern(64, 4)) == NULL) return TRUE;
-	UINT samplesize = (pfmt.channels * pfmt.bitspersample) >> 3;
-	UINT len = pdata.length, bytelen;
+	UINT samplesize = (pfmt->channels * pfmt->bitspersample) >> 3;
+	UINT len = pdata->length, bytelen;
 	if (dwMemPos + len > dwMemLength - 8) len = dwMemLength - dwMemPos - 8;
 	len /= samplesize;
 	bytelen = len;
-	if (pfmt.bitspersample >= 16) bytelen *= 2;
+	if (pfmt->bitspersample >= 16) bytelen *= 2;
 	if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
 	if (!len) return TRUE;
 	// Setting up module length
-	DWORD dwTime = ((len * 50) / pfmt.freqHz) + 1;
+	DWORD dwTime = ((len * 50) / pfmt->freqHz) + 1;
 	DWORD framesperrow = (dwTime + 63) / 63;
 	if (framesperrow < 4) framesperrow = 4;
 	UINT norders = 1;
@@ -115,7 +87,7 @@
 	pcmd[0].instr = 1;
 	pcmd[1].note = pcmd[0].note;
 	pcmd[1].instr = pcmd[0].instr;
-	m_nSamples = pfmt.channels;
+	m_nSamples = pfmt->channels;
 	// Support for Multichannel Wave
 	for (UINT nChn=0; nChn<m_nSamples; nChn++)
 	{
@@ -123,11 +95,11 @@
 		pcmd[nChn].note = pcmd[0].note;
 		pcmd[nChn].instr = (BYTE)(nChn+1);
 		pins->nLength = len;
-		pins->nC4Speed = pfmt.freqHz;
+		pins->nC4Speed = pfmt->freqHz;
 		pins->nVolume = 256;
 		pins->nPan = 128;
 		pins->nGlobalVol = 64;
-		pins->uFlags = (WORD)((pfmt.bitspersample >= 16) ? CHN_16BIT : 0);
+		pins->uFlags = (WORD)((pfmt->bitspersample >= 16) ? CHN_16BIT : 0);
 		pins->uFlags |= CHN_PANNING;
 		if (m_nSamples > 1)
 		{
@@ -141,14 +113,14 @@
 			}
 		}
 		if ((pins->pSample = AllocateSample(bytelen+8)) == NULL) return TRUE;
-		if (pfmt.bitspersample >= 16)
+		if (pfmt->bitspersample >= 16)
 		{
-			int slsize = pfmt.bitspersample >> 3;
+			int slsize = pfmt->bitspersample >> 3;
 			signed short *p = (signed short *)pins->pSample;
 			signed char *psrc = (signed char *)(lpStream+dwMemPos+8+nChn*slsize+slsize-2);
 			for (UINT i=0; i<len; i++)
 			{
-				p[i] = bswapLE16(*((signed short *)psrc));
+				p[i] = *((signed short *)psrc);
 				psrc += samplesize;
 			}
 			p[len+1] = p[len] = p[len-1];
@@ -212,8 +184,8 @@
 	while ((nPos < nLen) && (dwBytes > 4))
 	{
 		int nIndex;
-		value = bswapLE16(*((short int *)psrc));
-		nIndex = bswapLE16((short int)psrc[2]);
+		value = *((short int *)psrc);
+		nIndex = psrc[2];
 		psrc += 4;
 		dwBytes -= 4;
 		pdest[nPos++] = (short int)value;
@@ -228,7 +200,7 @@
 			{
 				delta = (BYTE)((*psrc) & 0x0F);
 			}
-			int v = gIMAUnpackTable[nIndex % 90] >> 3;
+			int v = gIMAUnpackTable[nIndex] >> 3;
 			if (delta & 1) v += gIMAUnpackTable[nIndex] >> 2;
 			if (delta & 2) v += gIMAUnpackTable[nIndex] >> 1;
 			if (delta & 4) v += gIMAUnpackTable[nIndex];
--- a/src/modplug/load_xm.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/load_xm.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -93,10 +93,10 @@
 	memcpy(m_szNames[0], lpStream+17, 20);
 	dwHdrSize = bswapLE32(*((DWORD *)(lpStream+60)));
 	norders = bswapLE16(*((WORD *)(lpStream+64)));
-	if (norders > MAX_ORDERS) return FALSE;
+	if ((!norders) || (norders > MAX_ORDERS)) return FALSE;
 	restartpos = bswapLE16(*((WORD *)(lpStream+66)));
 	channels = bswapLE16(*((WORD *)(lpStream+68)));
-	if (channels > 64) return FALSE;
+	if ((!channels) || (channels > 64)) return FALSE;
 	m_nType = MOD_TYPE_XM;
 	m_nMinPeriod = 27;
 	m_nMaxPeriod = 54784;
@@ -107,7 +107,6 @@
 	instruments = bswapLE16(*((WORD *)(lpStream+72)));
 	if (instruments >= MAX_INSTRUMENTS) instruments = MAX_INSTRUMENTS-1;
 	m_nInstruments = instruments;
-	m_dwSongFlags |= SONG_INSTRUMENTMODE;
 	m_nSamples = 0;
 	memcpy(&xmflags, lpStream+74, 2);
 	xmflags = bswapLE16(xmflags);
@@ -174,7 +173,6 @@
 		if (ipatmap < MAX_PATTERNS)
 		{
 			PatternSize[ipatmap] = rows;
-			PatternAllocSize[ipatmap] = rows;
 			if ((Patterns[ipatmap] = AllocatePattern(rows, m_nChannels)) == NULL) return TRUE;
 			if (!packsize) continue;
 			p = Patterns[ipatmap];
@@ -388,42 +386,42 @@
 		if (xmsh.ptype & 4) penv->dwFlags |= ENV_PANLOOP;
 		if (xmsh.vnum > 12) xmsh.vnum = 12;
 		if (xmsh.pnum > 12) xmsh.pnum = 12;
-		penv->VolEnv.nNodes = xmsh.vnum;
+		penv->nVolEnv = xmsh.vnum;
 		if (!xmsh.vnum) penv->dwFlags &= ~ENV_VOLUME;
 		if (!xmsh.pnum) penv->dwFlags &= ~ENV_PANNING;
-		penv->PanEnv.nNodes = xmsh.pnum;
-		penv->VolEnv.nSustainStart = penv->VolEnv.nSustainEnd = xmsh.vsustain;
+		penv->nPanEnv = xmsh.pnum;
+		penv->nVolSustainBegin = penv->nVolSustainEnd = xmsh.vsustain;
 		if (xmsh.vsustain >= 12) penv->dwFlags &= ~ENV_VOLSUSTAIN;
-		penv->VolEnv.nLoopStart = xmsh.vloops;
-		penv->VolEnv.nLoopEnd = xmsh.vloope;
-		if (penv->VolEnv.nLoopEnd >= 12) penv->VolEnv.nLoopEnd = 0;
-		if (penv->VolEnv.nLoopStart >= penv->VolEnv.nLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP;
-		penv->PanEnv.nSustainStart = penv->PanEnv.nSustainEnd = xmsh.psustain;
+		penv->nVolLoopStart = xmsh.vloops;
+		penv->nVolLoopEnd = xmsh.vloope;
+		if (penv->nVolLoopEnd >= 12) penv->nVolLoopEnd = 0;
+		if (penv->nVolLoopStart >= penv->nVolLoopEnd) penv->dwFlags &= ~ENV_VOLLOOP;
+		penv->nPanSustainBegin = penv->nPanSustainEnd = xmsh.psustain;
 		if (xmsh.psustain >= 12) penv->dwFlags &= ~ENV_PANSUSTAIN;
-		penv->PanEnv.nLoopStart = xmsh.ploops;
-		penv->PanEnv.nLoopEnd = xmsh.ploope;
-		if (penv->PanEnv.nLoopEnd >= 12) penv->PanEnv.nLoopEnd = 0;
-		if (penv->PanEnv.nLoopStart >= penv->PanEnv.nLoopEnd) penv->dwFlags &= ~ENV_PANLOOP;
-		penv->nGlobalVol = 128;
+		penv->nPanLoopStart = xmsh.ploops;
+		penv->nPanLoopEnd = xmsh.ploope;
+		if (penv->nPanLoopEnd >= 12) penv->nPanLoopEnd = 0;
+		if (penv->nPanLoopStart >= penv->nPanLoopEnd) penv->dwFlags &= ~ENV_PANLOOP;
+		penv->nGlobalVol = 64;
 		for (UINT ienv=0; ienv<12; ienv++)
 		{
-			penv->VolEnv.Ticks[ienv] = (WORD)xmsh.venv[ienv*2];
-			penv->VolEnv.Values[ienv] = (BYTE)xmsh.venv[ienv*2+1];
-			penv->PanEnv.Ticks[ienv] = (WORD)xmsh.penv[ienv*2];
-			penv->PanEnv.Values[ienv] = (BYTE)xmsh.penv[ienv*2+1];
+			penv->VolPoints[ienv] = (WORD)xmsh.venv[ienv*2];
+			penv->VolEnv[ienv] = (BYTE)xmsh.venv[ienv*2+1];
+			penv->PanPoints[ienv] = (WORD)xmsh.penv[ienv*2];
+			penv->PanEnv[ienv] = (BYTE)xmsh.penv[ienv*2+1];
 			if (ienv)
 			{
-				if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1])
+				if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1])
 				{
-					penv->VolEnv.Ticks[ienv] &= 0xFF;
-					penv->VolEnv.Ticks[ienv] += penv->VolEnv.Ticks[ienv-1] & 0xFF00;
-					if (penv->VolEnv.Ticks[ienv] < penv->VolEnv.Ticks[ienv-1]) penv->VolEnv.Ticks[ienv] += 0x100;
+					penv->VolPoints[ienv] &= 0xFF;
+					penv->VolPoints[ienv] += penv->VolPoints[ienv-1] & 0xFF00;
+					if (penv->VolPoints[ienv] < penv->VolPoints[ienv-1]) penv->VolPoints[ienv] += 0x100;
 				}
-				if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1])
+				if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1])
 				{
-					penv->PanEnv.Ticks[ienv] &= 0xFF;
-					penv->PanEnv.Ticks[ienv] += penv->PanEnv.Ticks[ienv-1] & 0xFF00;
-					if (penv->PanEnv.Ticks[ienv] < penv->PanEnv.Ticks[ienv-1]) penv->PanEnv.Ticks[ienv] += 0x100;
+					penv->PanPoints[ienv] &= 0xFF;
+					penv->PanPoints[ienv] += penv->PanPoints[ienv-1] & 0xFF00;
+					if (penv->PanPoints[ienv] < penv->PanPoints[ienv-1]) penv->PanPoints[ienv] += 0x100;
 				}
 			}
 		}
@@ -493,7 +491,7 @@
 			pins->nVibType = xmsh.vibtype;
 			pins->nVibSweep = xmsh.vibsweep;
 			pins->nVibDepth = xmsh.vibdepth;
-			pins->nVibRate = xmsh.vibrate/4;
+			pins->nVibRate = xmsh.vibrate;
 			memcpy(pins->name, xmss.name, 22);
 			pins->name[21] = 0;
 		}
@@ -513,12 +511,70 @@
 			if (dwMemPos >= dwMemLength) break;
 		}
 	}
-	/* set these to default */
-	for (UINT in=0; in<m_nChannels; in++)
+	// Read song comments: "TEXT"
+	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x74786574))
+	{
+		UINT len = *((DWORD *)(lpStream+dwMemPos+4));
+		dwMemPos += 8;
+		if ((dwMemPos + len <= dwMemLength) && (len < 16384))
+		{
+			m_lpszSongComments = new char[len+1];
+			if (m_lpszSongComments)
+			{
+				memcpy(m_lpszSongComments, lpStream+dwMemPos, len);
+				m_lpszSongComments[len] = 0;
+			}
+			dwMemPos += len;
+		}
+	}
+	// Read midi config: "MIDI"
+	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4944494D))
+	{
+		UINT len = *((DWORD *)(lpStream+dwMemPos+4));
+		dwMemPos += 8;
+		if (len == sizeof(MODMIDICFG))
+		{
+			memcpy(&m_MidiCfg, lpStream+dwMemPos, len);
+			m_dwSongFlags |= SONG_EMBEDMIDICFG;
+		}
+	}
+	// Read pattern names: "PNAM"
+	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50))
 	{
-		ChnSettings[in].nVolume = 64;
-		ChnSettings[in].nPan = 128;
-		ChnSettings[in].dwFlags = 0;
+		UINT len = *((DWORD *)(lpStream+dwMemPos+4));
+		dwMemPos += 8;
+		if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME))
+		{
+			m_lpszPatternNames = new char[len];
+
+			if (m_lpszPatternNames)
+			{
+				m_nPatternNames = len / MAX_PATTERNNAME;
+				memcpy(m_lpszPatternNames, lpStream+dwMemPos, len);
+			}
+			dwMemPos += len;
+		}
+	}
+	// Read channel names: "CNAM"
+	if ((dwMemPos + 8 < dwMemLength) && (bswapLE32(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e43))
+	{
+		UINT len = *((DWORD *)(lpStream+dwMemPos+4));
+		dwMemPos += 8;
+		if ((dwMemPos + len <= dwMemLength) && (len <= MAX_BASECHANNELS*MAX_CHANNELNAME))
+		{
+			UINT n = len / MAX_CHANNELNAME;
+			for (UINT i=0; i<n; i++)
+			{
+				memcpy(ChnSettings[i].szName, (lpStream+dwMemPos+i*MAX_CHANNELNAME), MAX_CHANNELNAME);
+				ChnSettings[i].szName[MAX_CHANNELNAME-1] = 0;
+			}
+			dwMemPos += len;
+		}
+	}
+	// Read mix plugins information
+	if (dwMemPos + 8 < dwMemLength)
+	{
+		dwMemPos += LoadMixPlugins(lpStream+dwMemPos, dwMemLength-dwMemPos);
 	}
 	return TRUE;
 }
@@ -526,7 +582,7 @@
 
 #ifndef MODPLUG_NO_FILESAVE
 
-BOOL CSoundFile::SaveXM(diskwriter_driver_t *fp, UINT nPacking)
+BOOL CSoundFile::SaveXM(LPCSTR lpszFileName, UINT nPacking)
 //---------------------------------------------------------
 {
 	BYTE s[64*64*5];
@@ -536,70 +592,51 @@
 	XMSAMPLESTRUCT xmss;
 	BYTE smptable[32];
 	BYTE xmph[9];
-	int i, np, ni, no;
-	UINT chanlim;
-
-	if (!fp) return FALSE;
+	FILE *f;
+	int i;
 
-	chanlim = GetHighestUsedChannel();
-	if (chanlim < 4) chanlim = 4;
-
-	fp->o(fp, (const unsigned char *)"Extended Module: ", 17);
-	fp->o(fp, (const unsigned char *)m_szNames[0], 20);
+	if ((!m_nChannels) || (!lpszFileName)) return FALSE;
+	if ((f = fopen(lpszFileName, "wb")) == NULL) return FALSE;
+	fwrite("Extended Module: ", 17, 1, f);
+	fwrite(m_szNames[0], 20, 1, f);
 	s[0] = 0x1A;
 	lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed   " : "FastTracker v2.00   ");
 	s[21] = 0x04;
 	s[22] = 0x01;
-	fp->o(fp, (const unsigned char *)s, 23);
+	fwrite(s, 23, 1, f);
 	// Writing song header
 	memset(&header, 0, sizeof(header));
-	header.size = bswapLE32(sizeof(XMFILEHEADER));
-	header.restartpos = bswapLE16(m_nRestartPos);
-	header.channels = bswapLE16(chanlim);
-	np = 0;
-	no = 0;
+	header.size = sizeof(XMFILEHEADER);
+	header.norder = 0;
+	header.restartpos = m_nRestartPos;
+	header.channels = m_nChannels;
+	header.patterns = 0;
 	for (i=0; i<MAX_ORDERS; i++)
 	{
 		if (Order[i] == 0xFF) break;
-		no++;
-		if ((Order[i] >= np) && (Order[i] < MAX_PATTERNS)) np = Order[i]+1;
+		header.norder++;
+		if ((Order[i] >= header.patterns) && (Order[i] < MAX_PATTERNS)) header.patterns = Order[i]+1;
 	}
-	header.patterns = bswapLE16(np);
-	if (m_nInstruments && (m_dwSongFlags & SONG_INSTRUMENTMODE))
-		ni = m_nInstruments;
-	else
-		ni = m_nSamples;
-	header.instruments = bswapLE16(ni);
+	header.instruments = m_nInstruments;
+	if (!header.instruments) header.instruments = m_nSamples;
 	header.flags = (m_dwSongFlags & SONG_LINEARSLIDES) ? 0x01 : 0x00;
 	if (m_dwSongFlags & SONG_EXFILTERRANGE) header.flags |= 0x1000;
-	header.tempo = bswapLE16(m_nDefaultTempo);
-	header.speed = bswapLE16(m_nDefaultSpeed);
-	header.flags = bswapLE16(header.flags);
-	header.norder = bswapLE16(no);
-	memcpy(header.order, Order, no);
-	fp->o(fp, (const unsigned char *)&header, sizeof(header));
+	header.tempo = m_nDefaultTempo;
+	header.speed = m_nDefaultSpeed;
+	memcpy(header.order, Order, header.norder);
+	fwrite(&header, 1, sizeof(header), f);
 	// Writing patterns
-	for (i=0; i<np; i++) if (Patterns[i])
+	for (i=0; i<header.patterns; i++) if (Patterns[i])
 	{
-		MODCOMMAND *pm = Patterns[i];
+		MODCOMMAND *p = Patterns[i];
 		UINT len = 0;
 
 		memset(&xmph, 0, sizeof(xmph));
 		xmph[0] = 9;
 		xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
 		xmph[6] = (BYTE)(PatternSize[i] >> 8);
-
-		UINT row = 0;
-		UINT col = 0;
-		for (UINT j=chanlim*PatternSize[i]; j; j--)
+		for (UINT j=m_nChannels*PatternSize[i]; j; j--,p++)
 		{
-			MODCOMMAND *p = &pm[col + row*m_nChannels];
-			col++;
-			if (col >= chanlim) {
-				col=0;
-				row++;
-			}
-
 			UINT note = p->note;
 			UINT param = ModSaveCommand(p, TRUE);
 			UINT command = param >> 8;
@@ -608,7 +645,6 @@
 			if ((note <= 12) || (note > 96+12)) note = 0; else
 			note -= 12;
 			UINT vol = 0;
-
 			if (p->volcmd)
 			{
 				UINT volcmd = p->volcmd;
@@ -653,31 +689,29 @@
 		}
 		xmph[7] = (BYTE)(len & 0xFF);
 		xmph[8] = (BYTE)(len >> 8);
-		fp->o(fp, (const unsigned char *)xmph, 9);
-		fp->o(fp, (const unsigned char *)s, len);
+		fwrite(xmph, 1, 9, f);
+		fwrite(s, 1, len, f);
 	} else
 	{
 		memset(&xmph, 0, sizeof(xmph));
 		xmph[0] = 9;
 		xmph[5] = (BYTE)(PatternSize[i] & 0xFF);
 		xmph[6] = (BYTE)(PatternSize[i] >> 8);
-		fp->o(fp, (const unsigned char *)xmph, 9);
+		fwrite(xmph, 1, 9, f);
 	}
 	// Writing instruments
-	for (i=1; i<=ni; i++)
+	for (i=1; i<=header.instruments; i++)
 	{
 		MODINSTRUMENT *pins;
-		int tmpsize, tmpsize2;
 		BYTE flags[32];
 
 		memset(&xmih, 0, sizeof(xmih));
 		memset(&xmsh, 0, sizeof(xmsh));
-		xmih.size = tmpsize = sizeof(xmih) + sizeof(xmsh);
-		xmih.size = bswapLE32(xmih.size);
+		xmih.size = sizeof(xmih) + sizeof(xmsh);
 		memcpy(xmih.name, m_szNames[i], 22);
 		xmih.type = 0;
 		xmih.samples = 0;
-		if (m_nInstruments && (m_dwSongFlags & SONG_INSTRUMENTMODE))
+		if (m_nInstruments)
 		{
 			INSTRUMENTHEADER *penv = Headers[i];
 			if (penv)
@@ -685,16 +719,16 @@
 				memcpy(xmih.name, penv->name, 22);
 				xmih.type = penv->nMidiProgram;
 				xmsh.volfade = penv->nFadeOut;
-				xmsh.vnum = (BYTE)penv->VolEnv.nNodes;
-				xmsh.pnum = (BYTE)penv->PanEnv.nNodes;
+				xmsh.vnum = (BYTE)penv->nVolEnv;
+				xmsh.pnum = (BYTE)penv->nPanEnv;
 				if (xmsh.vnum > 12) xmsh.vnum = 12;
 				if (xmsh.pnum > 12) xmsh.pnum = 12;
 				for (UINT ienv=0; ienv<12; ienv++)
 				{
-					xmsh.venv[ienv*2] = bswapLE16(penv->VolEnv.Ticks[ienv]);
-					xmsh.venv[ienv*2+1] = bswapLE16(penv->VolEnv.Values[ienv]);
-					xmsh.penv[ienv*2] = bswapLE16(penv->PanEnv.Ticks[ienv]);
-					xmsh.penv[ienv*2+1] = bswapLE16(penv->PanEnv.Values[ienv]);
+					xmsh.venv[ienv*2] = penv->VolPoints[ienv];
+					xmsh.venv[ienv*2+1] = penv->VolEnv[ienv];
+					xmsh.penv[ienv*2] = penv->PanPoints[ienv];
+					xmsh.penv[ienv*2+1] = penv->PanEnv[ienv];
 				}
 				if (penv->dwFlags & ENV_VOLUME) xmsh.vtype |= 1;
 				if (penv->dwFlags & ENV_VOLSUSTAIN) xmsh.vtype |= 2;
@@ -702,12 +736,12 @@
 				if (penv->dwFlags & ENV_PANNING) xmsh.ptype |= 1;
 				if (penv->dwFlags & ENV_PANSUSTAIN) xmsh.ptype |= 2;
 				if (penv->dwFlags & ENV_PANLOOP) xmsh.ptype |= 4;
-				xmsh.vsustain = (BYTE)penv->VolEnv.nSustainStart;
-				xmsh.vloops = (BYTE)penv->VolEnv.nLoopStart;
-				xmsh.vloope = (BYTE)penv->VolEnv.nLoopEnd;
-				xmsh.psustain = (BYTE)penv->PanEnv.nSustainStart;
-				xmsh.ploops = (BYTE)penv->PanEnv.nLoopStart;
-				xmsh.ploope = (BYTE)penv->PanEnv.nLoopEnd;
+				xmsh.vsustain = (BYTE)penv->nVolSustainBegin;
+				xmsh.vloops = (BYTE)penv->nVolLoopStart;
+				xmsh.vloope = (BYTE)penv->nVolLoopEnd;
+				xmsh.psustain = (BYTE)penv->nPanSustainBegin;
+				xmsh.ploops = (BYTE)penv->nPanLoopStart;
+				xmsh.ploope = (BYTE)penv->nPanLoopEnd;
 				for (UINT j=0; j<96; j++) if (penv->Keyboard[j+12])
 				{
 					UINT k;
@@ -728,7 +762,7 @@
 			smptable[0] = i;
 		}
 		xmsh.shsize = (xmih.samples) ? 40 : 0;
-		fp->o(fp, (const unsigned char *)&xmih, sizeof(xmih));
+		fwrite(&xmih, 1, sizeof(xmih), f);
 		if (smptable[0])
 		{
 			MODINSTRUMENT *pvib = &Ins[smptable[0]];
@@ -737,27 +771,17 @@
 			xmsh.vibdepth = pvib->nVibDepth;
 			xmsh.vibrate = pvib->nVibRate;
 		}
-
-		tmpsize2 = xmsh.shsize;
-		xmsh.shsize = bswapLE32(xmsh.shsize);
-		xmsh.volfade = bswapLE16(xmsh.volfade);
-		xmsh.res = bswapLE16(xmsh.res);
-
-		fp->o(fp, (const unsigned char *)&xmsh, tmpsize - sizeof(xmih));
+		fwrite(&xmsh, 1, xmih.size - sizeof(xmih), f);
 		if (!xmih.samples) continue;
 		for (UINT ins=0; ins<xmih.samples; ins++)
 		{
 			memset(&xmss, 0, sizeof(xmss));
 			if (smptable[ins]) memcpy(xmss.name, m_szNames[smptable[ins]], 22);
 			pins = &Ins[smptable[ins]];
-			/* convert IT information to FineTune */
-			FrequencyToTranspose(pins);
-
 			xmss.samplen = pins->nLength;
 			xmss.loopstart = pins->nLoopStart;
 			xmss.looplen = pins->nLoopEnd - pins->nLoopStart;
 			xmss.vol = pins->nVolume / 4;
-
 			xmss.finetune = (char)pins->nFineTune;
 			xmss.type = 0;
 			if (pins->uFlags & CHN_LOOP) xmss.type = (pins->uFlags & CHN_PINGPONGLOOP) ? 2 : 1;
@@ -766,7 +790,7 @@
 			if (nPacking)
 			{
 				if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
-				 && (CanPackSample((char*)pins->pSample, pins->nLength, nPacking)))
+				 && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking)))
 				{
 					flags[ins] = RS_ADPCM4;
 					xmss.res = 0xAD;
@@ -791,18 +815,10 @@
 					xmss.samplen *= 2;
 				}
 			}
-			if (pins->uFlags & CHN_PANNING) {
-				xmss.pan = 255;
-				if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan;
-			} else {
-				/* set panning to support default */
-				xmss.pan = 128;
-			}
+			xmss.pan = 255;
+			if (pins->nPan < 256) xmss.pan = (BYTE)pins->nPan;
 			xmss.relnote = (signed char)pins->RelativeTone;
-			xmss.samplen = bswapLE32(xmss.samplen);
-			xmss.loopstart = bswapLE32(xmss.loopstart);
-			xmss.looplen = bswapLE32(xmss.looplen);
-			fp->o(fp, (const unsigned char *)&xmss, tmpsize2);
+			fwrite(&xmss, 1, xmsh.shsize, f);
 		}
 		for (UINT ismpd=0; ismpd<xmih.samples; ismpd++)
 		{
@@ -810,12 +826,66 @@
 			if (pins->pSample)
 			{
 #ifndef NO_PACKING
-				if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample((char*)pins->pSample, pins->nLength, nPacking);
+				if ((flags[ismpd] == RS_ADPCM4) && (xmih.samples>1)) CanPackSample((char *)pins->pSample, pins->nLength, nPacking);
 #endif // NO_PACKING
-				WriteSample(fp, pins, flags[ismpd]);
+				WriteSample(f, pins, flags[ismpd]);
 			}
 		}
 	}
+	// Writing song comments
+	if ((m_lpszSongComments) && (m_lpszSongComments[0]))
+	{
+		DWORD d = 0x74786574;
+		fwrite(&d, 1, 4, f);
+		d = strlen(m_lpszSongComments);
+		fwrite(&d, 1, 4, f);
+		fwrite(m_lpszSongComments, 1, d, f);
+	}
+	// Writing midi cfg
+	if (m_dwSongFlags & SONG_EMBEDMIDICFG)
+	{
+		DWORD d = 0x4944494D;
+		fwrite(&d, 1, 4, f);
+		d = sizeof(MODMIDICFG);
+		fwrite(&d, 1, 4, f);
+		fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f);
+	}
+	// Writing Pattern Names
+	if ((m_nPatternNames) && (m_lpszPatternNames))
+	{
+		DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME;
+		while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME;
+		if (dwLen >= MAX_PATTERNNAME)
+		{
+			DWORD d = 0x4d414e50;
+			fwrite(&d, 1, 4, f);
+			fwrite(&dwLen, 1, 4, f);
+			fwrite(m_lpszPatternNames, 1, dwLen, f);
+		}
+	}
+	// Writing Channel Names
+	{
+		UINT nChnNames = 0;
+		for (UINT inam=0; inam<m_nChannels; inam++)
+		{
+			if (ChnSettings[inam].szName[0]) nChnNames = inam+1;
+		}
+		// Do it!
+		if (nChnNames)
+		{
+			DWORD dwLen = nChnNames * MAX_CHANNELNAME;
+			DWORD d = 0x4d414e43;
+			fwrite(&d, 1, 4, f);
+			fwrite(&dwLen, 1, 4, f);
+			for (UINT inam=0; inam<nChnNames; inam++)
+			{
+				fwrite(ChnSettings[inam].szName, 1, MAX_CHANNELNAME, f);
+			}
+		}
+	}
+	// Save mix plugins information
+	SaveMixPlugins(f);
+	fclose(f);
 	return TRUE;
 }
 
--- a/src/modplug/snd_dsp.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/snd_dsp.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -44,9 +44,6 @@
 UINT CSoundFile::m_nProLogicDepth = 12;
 UINT CSoundFile::m_nProLogicDelay = 20;
 
-void (*CSoundFile::_midi_out_note)(int chan, const MODCOMMAND *m) = NULL;
-void (*CSoundFile::_midi_out_raw)(unsigned char *,unsigned int, unsigned int) = NULL;
-
 ////////////////////////////////////////////////////////////////////
 // DSP Effects internal state
 
@@ -171,9 +168,6 @@
 			memset(ReverbBuffer3, 0, sizeof(ReverbBuffer3));
 			memset(ReverbBuffer4, 0, sizeof(ReverbBuffer4));
 			memset(gRvbLowPass, 0, sizeof(gRvbLowPass));
-/* mrsb: libmodplug bug hahahah */
-			memset(MixSoundBuffer,0,sizeof(MixSoundBuffer));
-			memset(MixReverbBuffer,0,sizeof(MixReverbBuffer));
 		}
 	} else nReverbSize = 0;
 #endif
@@ -474,12 +468,12 @@
 	return TRUE;
 }
 
-BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL /*bNoOverSampling*/,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ)
+BOOL CSoundFile::SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ)
 //----------------------------------------------------------------------------------------------------------------------------
 {
 	DWORD d = gdwSoundSetup & ~(SNDMIX_SURROUND | SNDMIX_NORESAMPLING | SNDMIX_REVERB | SNDMIX_HQRESAMPLER | SNDMIX_MEGABASS | SNDMIX_NOISEREDUCTION | SNDMIX_EQ);
 	if (bSurround) d |= SNDMIX_SURROUND;
-//	if (bNoOverSampling) d |= SNDMIX_NORESAMPLING;
+	if (bNoOverSampling) d |= SNDMIX_NORESAMPLING;
 	if (bReverb) d |= SNDMIX_REVERB;
 	if (hqido) d |= SNDMIX_HQRESAMPLER;
 	if (bMegaBass) d |= SNDMIX_MEGABASS;
--- a/src/modplug/snd_flt.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/snd_flt.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -9,122 +9,93 @@
 
 // AWE32: cutoff = reg[0-255] * 31.25 + 100 -> [100Hz-8060Hz]
 // EMU10K1 docs: cutoff = reg[0-127]*62+100
+#define FILTER_PRECISION	8192
 
 #ifndef NO_FILTER
 
-static int filter_cutoff[] = {
-     130,  132,  134,  136,  138,  140,  142,  144,
-     146,  148,  151,  153,  155,  157,  160,  162,
-     164,  167,  169,  172,  174,  177,  179,  182,
-     184,  187,  190,  193,  195,  198,  201,  204,
-     207,  210,  213,  216,  220,  223,  226,  229,
-     233,  236,  239,  243,  246,  250,  254,  257,
-     261,  265,  269,  273,  277,  281,  285,  289,
-     293,  297,  302,  306,  311,  315,  320,  324,
-     329,  334,  339,  344,  349,  354,  359,  364,
-     369,  375,  380,  386,  391,  397,  403,  409,
-     415,  421,  427,  433,  440,  446,  452,  459,
-     466,  472,  479,  486,  493,  501,  508,  515,
-     523,  530,  538,  546,  554,  562,  570,  578,
-     587,  595,  604,  613,  622,  631,  640,  649,
-     659,  668,  678,  688,  698,  708,  718,  729,
-     739,  750,  761,  772,  783,  795,  806,  818,
-     830,  842,  854,  867,  880,  892,  905,  918,
-     932,  945,  959,  973,  987, 1002, 1016, 1031,
-    1046, 1061, 1077, 1092, 1108, 1124, 1141, 1157,
-    1174, 1191, 1209, 1226, 1244, 1262, 1280, 1299,
-    1318, 1337, 1357, 1376, 1396, 1417, 1437, 1458,
-    1479, 1501, 1523, 1545, 1567, 1590, 1613, 1637,
-    1661, 1685, 1709, 1734, 1760, 1785, 1811, 1837,
-    1864, 1891, 1919, 1947, 1975, 2004, 2033, 2062,
-    2093, 2123, 2154, 2185, 2217, 2249, 2282, 2315,
-    2349, 2383, 2418, 2453, 2489, 2525, 2561, 2599,
-    2637, 2675, 2714, 2753, 2793, 2834, 2875, 2917,
-    2959, 3003, 3046, 3091, 3135, 3181, 3227, 3274,
-    3322, 3370, 3419, 3469, 3520, 3571, 3623, 3675,
-    3729, 3783, 3838, 3894, 3951, 4008, 4066, 4125,
-    4186, 4246, 4308, 4371, 4434, 4499, 4564, 4631,
-    4698, 4766, 4836, 4906, 4978, 5050, 5123, 5198
-};
-int dmpfac[] = {
-    131072, 128272, 125533, 122852, 120229, 117661, 115148, 112689,
-    110283, 107928, 105623, 103367, 101160,  98999,  96885,  94816,
-     92791,  90810,  88870,  86973,  85115,  83298,  81519,  79778,
-     78074,  76407,  74775,  73178,  71615,  70086,  68589,  67125,
-     65691,  64288,  62915,  61572,  60257,  58970,  57711,  56478,
-     55272,  54092,  52937,  51806,  50700,  49617,  48557,  47520,
-     46506,  45512,  44540,  43589,  42658,  41747,  40856,  39983,
-     39130,  38294,  37476,  36676,  35893,  35126,  34376,  33642,
-     32923,  32220,  31532,  30859,  30200,  29555,  28924,  28306,
-     27701,  27110,  26531,  25964,  25410,  24867,  24336,  23816,
-     23308,  22810,  22323,  21846,  21380,  20923,  20476,  20039,
-     19611,  19192,  18782,  18381,  17989,  17604,  17228,  16861,
-     16500,  16148,  15803,  15466,  15135,  14812,  14496,  14186,
-     13883,  13587,  13297,  13013,  12735,  12463,  12197,  11936,
-     11681,  11432,  11188,  10949,  10715,  10486,  10262,  10043,
-      9829,   9619,   9413,   9212,   9015,   8823,   8634,   8450,
-      8270,   8093,   7920,   7751,   7585,   7423,   7265,   7110,
-      6958,   6809,   6664,   6522,   6382,   6246,   6113,   5982,
-      5854,   5729,   5607,   5487,   5370,   5255,   5143,   5033,
-      4926,   4820,   4718,   4617,   4518,   4422,   4327,   4235,
-      4144,   4056,   3969,   3884,   3801,   3720,   3641,   3563,
-      3487,   3412,   3340,   3268,   3198,   3130,   3063,   2998,
-      2934,   2871,   2810,   2750,   2691,   2634,   2577,   2522,
-      2468,   2416,   2364,   2314,   2264,   2216,   2169,   2122,
-      2077,   2032,   1989,   1947,   1905,   1864,   1824,   1786,
-      1747,   1710,   1674,   1638,   1603,   1569,   1535,   1502,
-      1470,   1439,   1408,   1378,   1348,   1320,   1291,   1264,
-      1237,   1210,   1185,   1159,   1135,   1110,   1087,   1063,
-      1041,   1018,    997,    975,    955,    934,    914,    895,
-       876,    857,    838,    821,    803,    786,    769,    753,
-       737,    721,    705,    690,    676,    661,    647,    633,
-       620,    606,    593,    581,    568,    556,    544,    533
-};
+#ifdef MSC_VER
+#define _ASM_MATH
+#endif
+
+#ifdef _ASM_MATH
 
+// pow(a,b) returns a^^b -> 2^^(b.log2(a))
+static float pow(float a, float b)
+{
+	long tmpint;
+	float result;
+	_asm {
+	fld b				// Load b
+	fld a				// Load a
+	fyl2x				// ST(0) = b.log2(a)
+	fist tmpint			// Store integer exponent
+	fisub tmpint		// ST(0) = -1 <= (b*log2(a)) <= 1
+	f2xm1				// ST(0) = 2^(x)-1
+	fild tmpint			// load integer exponent
+	fld1				// Load 1
+	fscale				// ST(0) = 2^ST(1)
+	fstp ST(1)			// Remove the integer from the stack
+	fmul ST(1), ST(0)	// multiply with fractional part
+	faddp ST(1), ST(0)	// add integer_part
+	fstp result			// Store the result
+	}
+	return result;
+}
+
+
+#else
 
 #include <math.h>
 
+#endif // _ASM_MATH
 
-#define PI	((double)3.14159265358979323846)
+
+DWORD CSoundFile::CutOffToFrequency(UINT nCutOff, int flt_modifier) const
+//-----------------------------------------------------------------------
+{
+	float Fc;
+
+	if (m_dwSongFlags & SONG_EXFILTERRANGE)
+		Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(21.0f*512.0f));
+	else
+		Fc = 110.0f * pow(2.0f, 0.25f + ((float)(nCutOff*(flt_modifier+256)))/(24.0f*512.0f));
+	LONG freq = (LONG)Fc;
+	if (freq < 120) return 120;
+	if (freq > 10000) return 10000;
+	if (freq*2 > (LONG)gdwMixingFreq) freq = gdwMixingFreq>>1;
+	return (DWORD)freq;
+}
+
+
 // Simple 2-poles resonant filter
-void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier, int) const
+void CSoundFile::SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier) const
 //----------------------------------------------------------------------------------------
 {
-	int cutoff = pChn->nCutOff * 2;
-	cutoff *= (flt_modifier+256) / 2;
-	cutoff /= 256;
-	if (cutoff>=255) cutoff=255;
+	float fc = (float)CutOffToFrequency(pChn->nCutOff, flt_modifier);
+	float fs = (float)gdwMixingFreq;
+	float fg, fb0, fb1;
 
-	int resonance = pChn->nResonance;
-	if (resonance>=255) resonance=255;
-
-        float fc = (float)filter_cutoff[cutoff];
-        float fs = (float)gdwMixingFreq;
-        float fg, fb0, fb1;
-        float d2, d, e;
+	fc *= (float)(2.0*3.14159265358/fs);
+	float dmpfac = pow(10.0f, -((24.0f / 128.0f)*(float)pChn->nResonance) / 20.0f);
+	float d = (1.0f-2.0f*dmpfac)* fc;
+	if (d>2.0) d = 2.0;
+	d = (2.0f*dmpfac - d)/fc;
+	float e = pow(1.0f/fc,2.0);
 
-        fc *= 3.14159265358979 * 2 / fs;
-        d2 = ((float)dmpfac[resonance]) / 65536.0;
-        d = (1.0 - d2) * fc;
-
-        if (d > 2.0)
-                d = 2.0;
-
-        d = (d2 - d) / fc;
-        e = 1.0 / (fc * fc);
+	fg=1/(1+d+e);
+	fb0=(d+e+e)/(1+d+e);
+	fb1=-e/(1+d+e);
 
-        fg = 1.0 / (1 + d + e);
-        fb0 = (d + e + e) / (1 + d + e);
-        fb1 = -e / (1 + d + e);
+	pChn->nFilter_A0 = (int)(fg * FILTER_PRECISION);
+	pChn->nFilter_B0 = (int)(fb0 * FILTER_PRECISION);
+	pChn->nFilter_B1 = (int)(fb1 * FILTER_PRECISION);
 
-	pChn->nFilter_A0 = (double)fg;
-	pChn->nFilter_B0 = (double)fb0;
-	pChn->nFilter_B1 = (double)fb1;
-	
-	if (bReset) {
+	if (bReset)
+	{
 		pChn->nFilter_Y1 = pChn->nFilter_Y2 = 0;
 		pChn->nFilter_Y3 = pChn->nFilter_Y4 = 0;
 	}
 	pChn->dwFlags |= CHN_FILTER;
 }
+
 #endif // NO_FILTER
--- a/src/modplug/snd_fx.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/snd_fx.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -64,7 +64,6 @@
 		UINT nSpeedCount = 0;
 		nRow = nNextRow;
 		nCurrentPattern = nNextPattern;
-
 		// Check if pattern is valid
 		nPattern = Order[nCurrentPattern];
 		while (nPattern >= MAX_PATTERNS)
@@ -91,20 +90,6 @@
 			nNextPattern = nCurrentPattern + 1;
 			nNextRow = 0;
 		}
-		/* muahahaha */
-		if (stop_at_order > -1 && stop_at_row > -1) {
-			if (stop_at_order <= (signed) nCurrentPattern && stop_at_row <= (signed) nRow)
-				goto EndMod;
-			if (stop_at_time > 0) {
-				/* stupid api decision */
-				if (((dwElapsedTime+500) / 1000) >= stop_at_time) {
-					stop_at_order = nCurrentPattern;
-					stop_at_row = nRow;
-					goto EndMod;
-				}
-			}
-		}
-
 		if (!nRow)
 		{
 			for (UINT ipck=0; ipck<m_nChannels; ipck++) patloop[ipck] = dwElapsedTime;
@@ -170,7 +155,6 @@
 				}
 				if (param >= 0x20) nMusicTempo = param; else
 				// Tempo Slide
-				// FIXME: this is totally wrong!
 				if ((param & 0xF0) == 0x10)
 				{
 					nMusicTempo += param & 0x0F;
@@ -314,7 +298,7 @@
 	BOOL bInstrumentChanged = FALSE;
 
 	if (instr >= MAX_INSTRUMENTS) return;
-	INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL;
+	INSTRUMENTHEADER *penv = Headers[instr];
 	MODINSTRUMENT *psmp = &Ins[instr];
 	UINT note = pChn->nNewNote;
 	if ((penv) && (note) && (note <= 128))
@@ -322,9 +306,8 @@
 		if (penv->NoteMap[note-1] >= 0xFE) return;
 		UINT n = penv->Keyboard[note-1];
 		psmp = ((n) && (n < MAX_SAMPLES)) ? &Ins[n] : NULL;
-		pChn->dwFlags &= ~CHN_SUSTAINLOOP; // turn off sustain
 	} else
-	if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+	if (m_nInstruments)
 	{
 		if (note >= 0xFE) return;
 		psmp = NULL;
@@ -349,11 +332,9 @@
 	pChn->nNewIns = 0;
 	if (psmp)
 	{
-		psmp->played = 1;
 		if (penv)
 		{
-			penv->played = 1;
-			pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 7;
+			pChn->nInsVol = (psmp->nGlobalVol * penv->nGlobalVol) >> 6;
 			if (penv->dwFlags & ENV_SETPANNING) pChn->nPan = penv->nPan;
 			pChn->nNNA = penv->nNNA;
 		} else
@@ -440,38 +421,29 @@
 }
 
 
-void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv, BOOL bManual)
-//-----------------------------------------------------------------------------------------
+void CSoundFile::NoteChange(UINT nChn, int note, BOOL bPorta, BOOL bResetEnv)
+//---------------------------------------------------------------------------
 {
 	if (note < 1) return;
 	MODCHANNEL * const pChn = &Chn[nChn];
 	MODINSTRUMENT *pins = pChn->pInstrument;
-	INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL;
+	INSTRUMENTHEADER *penv = pChn->pHeader;
 	if ((penv) && (note <= 0x80))
 	{
 		UINT n = penv->Keyboard[note - 1];
 		if ((n) && (n < MAX_SAMPLES)) pins = &Ins[n];
 		note = penv->NoteMap[note-1];
-		pChn->dwFlags &= ~CHN_SUSTAINLOOP; // turn off sustain
 	}
 	// Key Off
 	if (note >= 0x80)	// 0xFE or invalid note => key off
 	{
-                // technically this is "wrong", as anything besides ^^^, ===, and a valid note
-		// should cause a note fade... (oh well, it's just a quick hack anyway.)
-                if (note == 0xFD) {
-			pChn->dwFlags |= CHN_NOTEFADE;
-                        return;
-                }
-                
 		// Key Off
 		KeyOff(nChn);
 		// Note Cut
 		if (note == 0xFE)
 		{
 			pChn->dwFlags |= (CHN_NOTEFADE|CHN_FASTVOLRAMP);
-			if ((!(m_nType & MOD_TYPE_IT)) || (m_dwSongFlags & SONG_INSTRUMENTMODE))
-				pChn->nVolume = 0;
+			if ((!(m_nType & MOD_TYPE_IT)) || (m_nInstruments)) pChn->nVolume = 0;
 			pChn->nFadeOutVol = 0;
 		}
 		return;
@@ -568,9 +540,8 @@
 					// Volume Swing
 					if (penv->nVolSwing)
 					{
-						/* this was wrong */
-						int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 256;
-						pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/256);
+						int d = ((LONG)penv->nVolSwing*(LONG)((rand() & 0xFF) - 0x7F)) / 128;
+						pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128);
 					}
 					// Pan Swing
 					if (penv->nPanSwing)
@@ -598,42 +569,21 @@
 		if ((pChn->nCutOff < 0x7F) && (bFlt)) SetupChannelFilter(pChn, TRUE);
 #endif // NO_FILTER
 	}
-	// Special case for MPT
-	if (bManual) pChn->dwFlags &= ~CHN_MUTE;
-	if (((pChn->dwFlags & CHN_MUTE) && (gdwSoundSetup & SNDMIX_MUTECHNMODE))
-	    || ((pChn->pInstrument) && (pChn->pInstrument->uFlags & CHN_MUTE) && (!bManual))
-	    || ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader)
-	        && (pChn->pHeader->dwFlags & ENV_MUTE) && (!bManual)))
-	{
-		if (!bManual) pChn->nPeriod = 0;
-	}
 }
 
 
-UINT CSoundFile::GetNNAChannel(UINT nChn)
+UINT CSoundFile::GetNNAChannel(UINT nChn) const
 //---------------------------------------------
 {
-	MODCHANNEL *pChn = &Chn[nChn];
+	const MODCHANNEL *pChn = &Chn[nChn];
 	// Check for empty channel
-	MODCHANNEL *pi = &Chn[m_nChannels];
-	for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, pi++) {
-		if (!pi->nLength) {
-			if (pi->dwFlags & CHN_MUTE) {
-				if (pi->dwFlags & CHN_NNAMUTE) {
-					pi->dwFlags &= ~(CHN_NNAMUTE|CHN_MUTE);
-				} else {
-					/* this channel is muted; skip */
-					continue;
-				}
-			}
-			return i;
-		}
-	}
+	const MODCHANNEL *pi = &Chn[m_nChannels];
+	for (UINT i=m_nChannels; i<MAX_CHANNELS; i++, pi++) if (!pi->nLength) return i;
 	if (!pChn->nFadeOutVol) return 0;
 	// All channels are used: check for lowest volume
 	UINT result = 0;
 	DWORD vol = 64*65536;	// 25%
-	int envpos = 0xFFFFFF;
+	DWORD envpos = 0xFFFFFF;
 	const MODCHANNEL *pj = &Chn[m_nChannels];
 	for (UINT j=m_nChannels; j<MAX_CHANNELS; j++, pj++)
 	{
@@ -651,10 +601,6 @@
 			result = j;
 		}
 	}
-	if (result) {
-		/* unmute new nna channel */
-		Chn[result].dwFlags &= ~(CHN_MUTE|CHN_NNAMUTE);
-	}
 	return result;
 }
 
@@ -662,25 +608,23 @@
 void CSoundFile::CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut)
 //------------------------------------------------------------------------
 {
-        MODCHANNEL *p;
 	MODCHANNEL *pChn = &Chn[nChn];
-	INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? pChn->pHeader : NULL;
-	INSTRUMENTHEADER *pHeader;
+	INSTRUMENTHEADER *penv = pChn->pHeader, *pHeader;
 	signed char *pSample;
 	if (note > 0x80) note = 0;
 	if (note < 1) return;
 	// Always NNA cut - using
-	if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!(m_dwSongFlags & SONG_INSTRUMENTMODE)) || (bForceCut))
+	if ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MT2))) || (!m_nInstruments) || (bForceCut))
 	{
 		if ((m_dwSongFlags & SONG_CPUVERYHIGH)
 		 || (!pChn->nLength) || (pChn->dwFlags & CHN_MUTE)
 		 || ((!pChn->nLeftVol) && (!pChn->nRightVol))) return;
 		UINT n = GetNNAChannel(nChn);
 		if (!n) return;
-		p = &Chn[n];
+		MODCHANNEL *p = &Chn[n];
 		// Copy Channel
 		*p = *pChn;
-		p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_PORTAMENTO);
+		p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
 		p->nMasterChn = nChn+1;
 		p->nCommand = 0;
 		// Cut the note
@@ -697,7 +641,7 @@
 	pHeader = pChn->pHeader;
 	if ((instr) && (note))
 	{
-		pHeader = (m_dwSongFlags & SONG_INSTRUMENTMODE) ? Headers[instr] : NULL;
+		pHeader = Headers[instr];
 		if (pHeader)
 		{
 			UINT n = 0;
@@ -710,7 +654,7 @@
 		} else pSample = NULL;
 	}
 	if (!penv) return;
-	p = pChn;
+	MODCHANNEL *p = pChn;
 	for (UINT i=nChn; i<MAX_CHANNELS; p++, i++)
 	if ((i >= m_nChannels) || (p == pChn))
 	{
@@ -722,7 +666,7 @@
 			{
 			// Note
 			case DCT_NOTE:
-				if ((note) && ((int)p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE;
+				if ((note) && (p->nNote == note) && (pHeader == p->pHeader)) bOk = TRUE;
 				break;
 			// Sample
 			case DCT_SAMPLE:
@@ -767,10 +711,10 @@
 		UINT n = GetNNAChannel(nChn);
 		if (n)
 		{
-			p = &Chn[n];
+			MODCHANNEL *p = &Chn[n];
 			// Copy Channel
 			*p = *pChn;
-			p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_PORTAMENTO);
+			p->dwFlags &= ~(CHN_VIBRATO|CHN_TREMOLO|CHN_PANBRELLO|CHN_MUTE|CHN_PORTAMENTO);
 			p->nMasterChn = nChn+1;
 			p->nCommand = 0;
 			// Key Off the note
@@ -801,19 +745,17 @@
 	MODCHANNEL *pChn = Chn;
 	for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++)
 	{
-		pChn->nCommand=0;
-
 		UINT instr = pChn->nRowInstr;
 		UINT volcmd = pChn->nRowVolCmd;
 		UINT vol = pChn->nRowVolume;
 		UINT cmd = pChn->nRowCommand;
 		UINT param = pChn->nRowParam;
 		BOOL bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? FALSE : TRUE;
-		UINT nStartTick = pChn->nTickStart;
+		UINT nStartTick = 0;
 
 		pChn->dwFlags &= ~CHN_FASTVOLRAMP;
 		// Process special effects (note delay, pattern delay, pattern loop)
-		if (((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX)))
+		if ((cmd == CMD_MODCMDEX) || (cmd == CMD_S3MCMDEX))
 		{
 			if ((!param) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))) param = pChn->nOldCmdEx; else pChn->nOldCmdEx = param;
 			// Note Delay ?
@@ -855,7 +797,7 @@
 			}
 			if ((!note) && (instr))
 			{
-				if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+				if (m_nInstruments)
 				{
 					if (pChn->pInstrument) pChn->nVolume = pChn->pInstrument->nVolume;
 					if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
@@ -880,7 +822,7 @@
 			// Note Cut/Off => ignore instrument
 			if (note >= 0xFE) instr = 0;
 			if ((note) && (note <= 128)) pChn->nNewNote = note;
-			// New Note Action ? (not when paused!!!)
+			// New Note Action ?
 			if ((note) && (note <= 128) && (!bPorta))
 			{
 				CheckNNA(nChn, instr, note, FALSE);
@@ -929,7 +871,6 @@
 				if (vol > 64) vol = 64;
 				pChn->nPan = vol << 2;
 				pChn->dwFlags |= CHN_FASTVOLRAMP;
-				pChn->dwFlags &= ~CHN_SURROUND;
 			}
 		}
 
@@ -1007,14 +948,6 @@
 			{
 				pChn->nVolume = (param < 64) ? param*4 : 256;
 				pChn->dwFlags |= CHN_FASTVOLRAMP;
-				for (UINT i=m_nChannels; i<MAX_CHANNELS; i++)
-				{
-					MODCHANNEL *c = &Chn[i];
-					if (c->nMasterChn == (nChn+1)) {
-						c->nVolume = pChn->nVolume;
-						c->dwFlags |= CHN_FASTVOLRAMP;
-					}
-				}
 			}
 			break;
 
@@ -1071,22 +1004,7 @@
 					if (param) pChn->nOldTempo = param; else param = pChn->nOldTempo;
 				}
 				SetTempo(param);
-			} else {
-                                param = pChn->nOldTempo; // this just got set on tick zero
-                                
-                                switch (param >> 4) {
-                                case 0:
-                                        m_nMusicTempo -= param & 0xf;
-                                        if (m_nMusicTempo < 32)
-                                                m_nMusicTempo = 32;
-                                        break;
-                                case 1:
-                                        m_nMusicTempo += param & 0xf;
-                                        if (m_nMusicTempo > 255)
-                                                m_nMusicTempo = 255;
-                                        break;
-                                }
-                        }
+			}
 			break;
 
 		// Set Offset
@@ -1121,9 +1039,9 @@
 
 		// Arpeggio
 		case CMD_ARPEGGIO:
-			pChn->nCommand = CMD_ARPEGGIO;
 			if ((m_nTickCount) || (!pChn->nPeriod) || (!pChn->nNote)) break;
 			if ((!param) && (!(m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT)))) break;
+			pChn->nCommand = CMD_ARPEGGIO;
 			if (param) pChn->nArpeggio = param;
 			break;
 
@@ -1135,18 +1053,14 @@
 				if (!(param & 0x0F)) param |= pChn->nRetrigParam & 0x0F;
 				param |= 0x100; // increment retrig count on first row
 			}
-			// various bits of retriggery commented out here & below, reverting to old method...
-			// -Storlek 04aug07
-			// if (pChn->nRowNote && !m_nTickCount) pChn->nRetrigCount = 0;
 			if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam;
-			// pChn->nCommand = CMD_RETRIG;
 			RetrigNote(nChn, param);
 			break;
 
 		// Tremor
 		case CMD_TREMOR:
+			if (m_nTickCount) break;
 			pChn->nCommand = CMD_TREMOR;
-			if (m_nTickCount) break;
 			if (param) pChn->nTremorParam = param;
 			break;
 
@@ -1235,35 +1149,12 @@
 			{
 				pChn->nGlobalVol = param;
 				pChn->dwFlags |= CHN_FASTVOLRAMP;
-				for (UINT i=m_nChannels; i<MAX_CHANNELS; i++)
-				{
-					MODCHANNEL *c = &Chn[i];
-					if (c->nMasterChn == (nChn+1)) {
-						c->nGlobalVol = param;
-						c->dwFlags |= CHN_FASTVOLRAMP;
-					}
-				}
 			}
 			break;
 
 		// Channel volume slide
 		case CMD_CHANNELVOLSLIDE:
-			{
-				int saw_self = 0;
-
-				for (UINT i=m_nChannels; i<MAX_CHANNELS; i++)
-				{
-					MODCHANNEL *c = &Chn[i];
-					if (c->nMasterChn == (nChn+1)) {
-						if (c == pChn) saw_self = 1;
-						ChannelVolSlide(c, param);
-					}
-				}
-				if (!saw_self) {
-					ChannelVolSlide(pChn, param);
-				}
-			}
-			
+			ChannelVolSlide(pChn, param);
 			break;
 
 		// Panbrello (IT)
@@ -1278,10 +1169,10 @@
 				pChn->nVolEnvPosition = param;
 				pChn->nPanEnvPosition = param;
 				pChn->nPitchEnvPosition = param;
-				if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+				if (pChn->pHeader)
 				{
 					INSTRUMENTHEADER *penv = pChn->pHeader;
-					if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes) && ((int)param > penv->PanEnv.Ticks[penv->PanEnv.nNodes-1]))
+					if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv) && (param > penv->PanPoints[penv->nPanEnv-1]))
 					{
 						pChn->dwFlags &= ~CHN_PANENV;
 					}
@@ -1376,8 +1267,6 @@
 //---------------------------------------------------------
 {
 	if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
-	if (m_dwSongFlags & SONG_ITCOMPATMODE) pChn->nPortamentoSlide=param*4;
-	else pChn->nPortamentoDest=0;
 	if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
 	{
 		if (param & 0x0F)
@@ -1405,8 +1294,6 @@
 //-----------------------------------------------------------
 {
 	if (param) pChn->nOldPortaUpDown = param; else param = pChn->nOldPortaUpDown;
-	if (m_dwSongFlags & SONG_ITCOMPATMODE) pChn->nPortamentoSlide=param*4;
-	else pChn->nPortamentoDest=0;
 	if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM)) && ((param & 0xF0) >= 0xE0))
 	{
 		if (param & 0x0F)
@@ -1679,7 +1566,6 @@
 		if (nPanSlide > 256) nPanSlide = 256;
 		pChn->nPan = nPanSlide;
 	}
-	pChn->dwFlags &= ~CHN_SURROUND;
 }
 
 
@@ -1853,29 +1739,17 @@
 				}
 				break;
 	// S8x: Set 4-bit Panning
-	case 0x80:
-			pChn->dwFlags &= ~CHN_SURROUND;
-			if (!m_nTickCount) {
-				pChn->nPan = (param << 4) + 8;
-				pChn->dwFlags |= CHN_FASTVOLRAMP;
-			}
-			break;
+	case 0x80:	if (!m_nTickCount) { pChn->nPan = (param << 4) + 8; pChn->dwFlags |= CHN_FASTVOLRAMP; } break;
 	// S9x: Set Surround
 	case 0x90:	ExtendedChannelEffect(pChn, param & 0x0F); break;
 	// SAx: Set 64k Offset
 	case 0xA0:	if (!m_nTickCount)
 				{
-					if (m_nType & MOD_TYPE_S3M) {
-						pChn->nPan = ((param ^ 8) << 4) + 8;
-						pChn->dwFlags &= ~CHN_SURROUND;
-						pChn->dwFlags |= CHN_FASTVOLRAMP;
-					} else {
-						pChn->nOldHiOffset = param;
-						if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
-						{
-							DWORD pos = param << 16;
-							if (pos < pChn->nLength) pChn->nPos = pos;
-						}
+					pChn->nOldHiOffset = param;
+					if ((pChn->nRowNote) && (pChn->nRowNote < 0x80))
+					{
+						DWORD pos = param << 16;
+						if (pos < pChn->nLength) pChn->nPos = pos;
 					}
 				}
 				break;
@@ -1898,12 +1772,12 @@
 	if (m_nTickCount) return;
 	switch(param & 0x0F)
 	{
-        // S91: Surround On
+	// S90: Surround Off
+	case 0x00:	pChn->dwFlags &= ~CHN_SURROUND;	break;
+	// S91: Surround On
 	case 0x01:	pChn->dwFlags |= CHN_SURROUND; pChn->nPan = 128; break;
 	////////////////////////////////////////////////////////////
 	// Modplug Extensions
-	// S90: Surround Off
-	case 0x00:	pChn->dwFlags &= ~CHN_SURROUND;	break;
 	// S98: Reverb Off
 	case 0x08:
 		pChn->dwFlags &= ~CHN_REVERB;
@@ -1946,176 +1820,102 @@
 	}
 }
 
-// this is all brisby
-void CSoundFile::MidiSend(unsigned char *data, unsigned int len, UINT nChn, int fake)
+
+void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param)
+//---------------------------------------------------------------------------
 {
 	MODCHANNEL *pChn = &Chn[nChn];
-	int oldcutoff;
+	DWORD dwMacro = (*((LPDWORD)pszMidiMacro)) & 0x7F5F7F5F;
+	// Not Internal Device ?
+	if (dwMacro != 0x30463046)
+	{
+		UINT pos = 0, nNib = 0, nBytes = 0;
+		DWORD dwMidiCode = 0, dwByteCode = 0;
+		while (pos+6 <= 32)
+		{
+			CHAR cData = pszMidiMacro[pos++];
+			if (!cData) break;
+			if ((cData >= '0') && (cData <= '9')) { dwByteCode = (dwByteCode<<4) | (cData-'0'); nNib++; } else
+			if ((cData >= 'A') && (cData <= 'F')) { dwByteCode = (dwByteCode<<4) | (cData-'A'+10); nNib++; } else
+			if ((cData >= 'a') && (cData <= 'f')) { dwByteCode = (dwByteCode<<4) | (cData-'a'+10); nNib++; } else
+			if ((cData == 'z') || (cData == 'Z')) { dwByteCode = param & 0x7f; nNib = 2; } else
+			if ((cData == 'x') || (cData == 'X')) { dwByteCode = param & 0x70; nNib = 2; } else
+			if ((cData == 'y') || (cData == 'Y')) { dwByteCode = (param & 0x0f)<<3; nNib = 2; } else
+			if (nNib >= 2)
+			{
+				nNib = 0;
+				dwMidiCode |= dwByteCode << (nBytes*8);
+				dwByteCode = 0;
+				nBytes++;
+				if (nBytes >= 3)
+				{
+					UINT nMasterCh = (nChn < m_nChannels) ? nChn+1 : pChn->nMasterChn;
+					if ((nMasterCh) && (nMasterCh <= m_nChannels))
+					{
+						UINT nPlug = ChnSettings[nMasterCh-1].nMixPlugin;
+						if ((nPlug) && (nPlug <= MAX_MIXPLUGINS))
+						{
+							IMixPlugin *pPlugin = m_MixPlugins[nPlug-1].pMixPlugin;
+							if ((pPlugin) && (m_MixPlugins[nPlug-1].pMixState))
+							{
+								pPlugin->MidiSend(dwMidiCode);
+							}
+						}
+					}
+					nBytes = 0;
+					dwMidiCode = 0;
+				}
+			}
 
-	if (len > 2 && data[0] == 0xF0 && data[1] == 0xF0) {
-		/* impulse tracker filter control (mfg. 0xF0) */
-		if (len == 5) {
-			switch (data[2]) {
-			case 0x00: /* set cutoff */
-				oldcutoff = pChn->nCutOff;
-				if (data[3] < 0x80) pChn->nCutOff = data[3];
+		}
+		return;
+	}
+	// Internal device
+	pszMidiMacro += 4;
+	// Filter ?
+	if (pszMidiMacro[0] == '0')
+	{
+		CHAR cData1 = pszMidiMacro[2];
+		DWORD dwParam = 0;
+		if ((cData1 == 'z') || (cData1 == 'Z'))
+		{
+			dwParam = param;
+		} else
+		{
+			CHAR cData2 = pszMidiMacro[3];
+			if ((cData1 >= '0') && (cData1 <= '9')) dwParam += (cData1 - '0') << 4; else
+			if ((cData1 >= 'A') && (cData1 <= 'F')) dwParam += (cData1 - 'A' + 0x0A) << 4;
+			if ((cData2 >= '0') && (cData2 <= '9')) dwParam += (cData2 - '0'); else
+			if ((cData2 >= 'A') && (cData2 <= 'F')) dwParam += (cData2 - 'A' + 0x0A);
+		}
+		switch(pszMidiMacro[1])
+		{
+		// F0.F0.00.xx: Set CutOff
+		case '0':
+			{
+				int oldcutoff = pChn->nCutOff;
+				if (dwParam < 0x80) pChn->nCutOff = dwParam;
 #ifndef NO_FILTER
 				oldcutoff -= pChn->nCutOff;
 
 				if (oldcutoff < 0) oldcutoff = -oldcutoff;
 				if ((pChn->nVolume > 0) || (oldcutoff < 0x10)
-				 || (!(pChn->dwFlags & CHN_FILTER))
-				|| (!(pChn->nLeftVol|pChn->nRightVol)))
-					SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER)
-							? FALSE : TRUE);
-#endif // NO_FILTER
-				break;
-			case 0x01: /* set resonance */
-				if (data[3] < 0x80) pChn->nResonance = data[3];
-#ifndef NO_FILTER
-				SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE);
+				 || (!(pChn->dwFlags & CHN_FILTER)) || (!(pChn->nLeftVol|pChn->nRightVol)))
+					SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE);
 #endif // NO_FILTER
-				break;
-			};
-		}
-	}
-
-	if (!fake && _midi_out_raw) {
-		/* okay, this is kind of how it works.
-		we pass m_nBufferCount as here because while
-			1000 * ((8((buffer_size/2) - m_nBufferCount)) / sample_rate)
-		is the number of msec we need to delay by, libmodplug simply doesn't know
-		what the buffer size is at this point so m_nBufferCount simply has no
-		frame of reference.
-
-		fortunately, schism does and can complete this (tags: _schism_midi_out_raw )
-
-		*/
-		_midi_out_raw(data, len, m_nBufferCount);
-	}
-}
-
-static int _was_complete_midi(unsigned char *q, unsigned int len, int nextc)
-{
-	if (len == 0) return 0;
-	if (*q == 0xF0) return (q[len-1] == 0xF7 ? 1 : 0);
-	return ((nextc & 0x80) ? 1 : 0);
-}
-
-void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param,
-			UINT note, UINT velocity, UINT use_instr)
-//---------------------------------------------------------------------------
-{
-/* this was all wrong. -mrsb */
-	MODCHANNEL *pChn = &Chn[nChn];
-	INSTRUMENTHEADER *penv = (m_dwSongFlags & SONG_INSTRUMENTMODE)
-			? Headers[use_instr
-					?use_instr
-					:pChn->nLastInstr]
-			: NULL;
-	unsigned char outbuffer[64];
-	unsigned char cx;
-	int mc, fake = 0;
-	int saw_c;
-	int i, j, x;
-
-	saw_c = 0;
-	if (!penv || penv->nMidiChannel == 0) {
-		/* okay, there _IS_ no real midi channel. forget this for now... */
-		mc = 15;
-		fake = 1;
-
-	} else if (penv->nMidiChannel > 16) {
-		mc = (nChn-1) % 16;
-	} else {
-		mc = (penv->nMidiChannel-1);
-	}
+			}
+			break;
 
-	for (i = j = x = 0, cx =0; i <= 32 && pszMidiMacro[i]; i++) {
-		int c, cw;
-		if (pszMidiMacro[i] >= '0' && pszMidiMacro[i] <= '9') {
-			c = pszMidiMacro[i] - '0';
-			cw = 1;
-		} else if (pszMidiMacro[i] >= 'A' && pszMidiMacro[i] <= 'F') {
-			c = (pszMidiMacro[i] - 'A') + 10;
-			cw = 1;
-		} else if (pszMidiMacro[i] == 'c') {
-			c = mc;
-			cw = 1;
-			saw_c = 1;
-		} else if (pszMidiMacro[i] == 'n') {
-			c = (note-1);
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'v') {
-			c = velocity;
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'u') {
-			c = (pChn->nVolume >> 1);
-			if (c > 127) c = 127;
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'x') {
-			c = pChn->nPan;
-			if (c > 127) c = 127;
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'y') {
-			c = pChn->nRealPan;
-			if (c > 127) c = 127;
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'a') {
-			if (!penv)
-				c = 0;
-			else
-				c = (penv->wMidiBank >> 7) & 127;
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'b') {
-			if (!penv)
-				c = 0;
-			else
-				c = penv->wMidiBank & 127;
-			cw = 2;
-		} else if (pszMidiMacro[i] == 'z' || pszMidiMacro[i] == 'p') {
-			c = param & 0x7F;
-			cw = 2;
-		} else {
-			continue;
+		// F0.F0.01.xx: Set Resonance
+		case '1':
+			if (dwParam < 0x80) pChn->nResonance = dwParam;
+#ifndef NO_FILTER
+			SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE);
+#endif // NO_FILTER
+
+			break;
 		}
-		if (j == 0 && cw == 1) {
-			cx = c;
-			j = 1;
-			continue;
-		} else if (j == 1 && cw == 1) {
-			cx = (cx << 4) | c;
-			j = 0;
-		} else if (j == 0) {
-			cx = c;
-		} else if (j == 1) {
-			outbuffer[x] = cx;
-			x++;
 
-			cx = c;
-			j = 0;
-		}
-		// start of midi message
-		if (_was_complete_midi(outbuffer,x,cx)) {
-			MidiSend(outbuffer, x, nChn,saw_c && fake);
-			x = 0;
-		}
-		outbuffer[x] = cx;
-		x++;
-	}
-	if (j == 1) {
-		outbuffer[x] = cx;
-		x++;
-	}
-	if (x) {
-		// terminate sysex
-		if (!_was_complete_midi(outbuffer,x,0xFF)) {
-			if (*outbuffer == 0xF0) {
-				outbuffer[x] = 0xF7;
-				x++;
-			}
-		}
-		MidiSend(outbuffer, x, nChn,saw_c && fake);
 	}
 }
 
@@ -2132,18 +1932,10 @@
 	if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT))
 	{
 		if (!nRetrigSpeed) nRetrigSpeed = 1;
-		if (m_nMusicSpeed < nRetrigSpeed) {
-			if (nRetrigCount >= nRetrigSpeed) {
-				bDoRetrig = TRUE;
-				nRetrigCount = 0;
-			} else {
-				nRetrigCount++;
-			}
-		} else {
-			if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE;
-			nRetrigCount++;
-		}
-	} else {
+		if ((nRetrigCount) && (!(nRetrigCount % nRetrigSpeed))) bDoRetrig = TRUE;
+		nRetrigCount++;
+	} else
+	{
 		UINT realspeed = nRetrigSpeed;
 		if ((param & 0x100) && (pChn->nRowVolCmd == VOLCMD_VOLUME) && (pChn->nRowParam & 0xF0)) realspeed++;
 		if ((m_nTickCount) || (param & 0x100))
@@ -2230,10 +2022,9 @@
 	if (m_nTickCount == nTick)
 	{
 		MODCHANNEL *pChn = &Chn[nChn];
-		// if (m_dwSongFlags & SONG_INSTRUMENTMODE) KeyOff(pChn); ?
+		// if (m_nInstruments) KeyOff(pChn); ?
 		pChn->nVolume = 0;
 		pChn->dwFlags |= CHN_FASTVOLRAMP;
-		pChn->nLength = 0;
 	}
 }
 
@@ -2245,7 +2036,7 @@
 	BOOL bKeyOn = (pChn->dwFlags & CHN_KEYOFF) ? FALSE : TRUE;
 	pChn->dwFlags |= CHN_KEYOFF;
 	//if ((!pChn->pHeader) || (!(pChn->dwFlags & CHN_VOLENV)))
-	if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV)))
+	if ((pChn->pHeader) && (!(pChn->dwFlags & CHN_VOLENV)))
 	{
 		pChn->dwFlags |= CHN_NOTEFADE;
 	}
@@ -2270,7 +2061,7 @@
 			pChn->nLength = psmp->nLength;
 		}
 	}
-	if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+	if (pChn->pHeader)
 	{
 		INSTRUMENTHEADER *penv = pChn->pHeader;
 		if (((penv->dwFlags & ENV_VOLLOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (penv->nFadeOut))
@@ -2286,8 +2077,22 @@
 void CSoundFile::SetSpeed(UINT param)
 //-----------------------------------
 {
-        if (param)
-                m_nMusicSpeed = param;
+	UINT max = (m_nType == MOD_TYPE_IT) ? 256 : 128;
+	// Modplug Tracker and Mod-Plugin don't do this check
+#ifndef MODPLUG_TRACKER
+#ifndef MODPLUG_FASTSOUNDLIB
+	// Big Hack!!!
+	if ((!param) || (param >= 0x80) || ((m_nType & (MOD_TYPE_MOD|MOD_TYPE_XM|MOD_TYPE_MT2)) && (param >= 0x1E)))
+	{
+		if (IsSongFinished(m_nCurrentPattern, m_nRow+1))
+		{
+			GlobalFadeSong(1000);
+		}
+	}
+#endif // MODPLUG_FASTSOUNDLIB
+#endif // MODPLUG_TRACKER
+	if ((m_nType & MOD_TYPE_S3M) && (param > 0x80)) param -= 0x80;
+	if ((param) && (param <= max)) m_nMusicSpeed = param;
 }
 
 
@@ -2296,7 +2101,6 @@
 {
 	if (param < 0x20)
 	{
-#if 0 // argh... this is completely wrong
 		// Tempo Slide
 		if ((param & 0xF0) == 0x10)
 		{
@@ -2307,7 +2111,6 @@
 			m_nMusicTempo -= (param & 0x0F) * 2;
 			if ((LONG)m_nMusicTempo < 32) m_nMusicTempo = 32;
 		}
-#endif
 	} else
 	{
 		m_nMusicTempo = param;
@@ -2323,28 +2126,15 @@
 		if (pChn->nPatternLoopCount)
 		{
 			pChn->nPatternLoopCount--;
-			if (!pChn->nPatternLoopCount) {
-                                // this should get rid of that nasty infinite loop for cases like
-                                //     ... .. .. SB0
-                                //     ... .. .. SB1
-                                //     ... .. .. SB1
-                                // it still doesn't work right in a few strange cases, but oh well :P
-                                pChn->nPatternLoop = m_nRow + 1;
-                                return -1;
-                        }
+			if (!pChn->nPatternLoopCount) return -1;
 		} else
 		{
-                        // hmm. the pattern loop shouldn't care about
-                        // other channels at all... i'm not really
-                        // sure what this code is doing :/
-#if 0
 			MODCHANNEL *p = Chn;
 			for (UINT i=0; i<m_nChannels; i++, p++) if (p != pChn)
 			{
 				// Loop already done
 				if (p->nPatternLoopCount) return -1;
 			}
-#endif
 			pChn->nPatternLoopCount = param;
 		}
 		return pChn->nPatternLoop;
@@ -2507,33 +2297,6 @@
 	}
 }
 
-// this last param was nC4Speed
-UINT CSoundFile::GetLinearPeriodFromNote(UINT note, int nFineTune, UINT) const
-{
-	if ((!note) || (note > 0xF0)) return 0;
-	if (m_nType & (MOD_TYPE_IT|MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_MDL|MOD_TYPE_ULT|MOD_TYPE_WAV
-				|MOD_TYPE_FAR|MOD_TYPE_DMF|MOD_TYPE_PTM|MOD_TYPE_AMS|MOD_TYPE_DBM|MOD_TYPE_AMF|MOD_TYPE_PSM))
-	{
-		note--;
-		return (FreqS3MTable[note % 12] << 5) >> (note / 12);
-	} else
-	if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
-	{
-		if (note < 13) note = 13;
-		note -= 13;
-		LONG l = ((120 - note) << 6) - (nFineTune / 2);
-		if (l < 1) l = 1;
-		return (UINT)l;
-	} else
-	{
-		note--;
-		nFineTune = XM2MODFineTune(nFineTune);
-		if ((nFineTune) || (note < 36) || (note >= 36+6*12))
-			return (ProTrackerTunedPeriods[nFineTune*12 + note % 12] << 5) >> (note / 12);
-		else
-			return (ProTrackerPeriodTable[note-36] << 2);
-	}
-}
 
 
 UINT CSoundFile::GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const
--- a/src/modplug/sndfile.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/sndfile.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -15,7 +15,6 @@
 extern BOOL MMCMP_Unpack(LPCBYTE *ppMemFile, LPDWORD pdwMemLength);
 #endif
 
-
 // External decompressors
 extern void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter);
 extern WORD MDLReadBits(DWORD &bitbuf, UINT &bitnum, LPBYTE &ibuf, CHAR n);
@@ -51,7 +50,6 @@
 {
 	m_nType = MOD_TYPE_NONE;
 	m_dwSongFlags = 0;
-	m_nStereoSeparation = 128;
 	m_nChannels = 0;
 	m_nMixChannels = 0;
 	m_nSamples = 0;
@@ -64,8 +62,6 @@
 	m_nMinPeriod = 0x20;
 	m_nMaxPeriod = 0x7FFF;
 	m_nRepeatCount = 0;
-	m_rowHighlightMajor = 16;
-	m_rowHighlightMinor = 4;
 	memset(Chn, 0, sizeof(Chn));
 	memset(ChnMix, 0, sizeof(ChnMix));
 	memset(Ins, 0, sizeof(Ins));
@@ -90,10 +86,8 @@
 {
 	int i;
 
-	// deja vu...
 	m_nType = MOD_TYPE_NONE;
 	m_dwSongFlags = 0;
-	m_nStereoSeparation = 128;
 	m_nChannels = 0;
 	m_nMixChannels = 0;
 	m_nSamples = 0;
@@ -117,6 +111,7 @@
 	m_nMaxPeriod = 32767;
 	m_nSongPreAmp = 0x30;
 	m_nPatternNames = 0;
+	m_nMaxOrderPosition = 0;
 	m_lpszPatternNames = NULL;
 	m_lpszSongComments = NULL;
 	memset(Ins, 0, sizeof(Ins));
@@ -128,10 +123,7 @@
 	memset(m_szNames, 0, sizeof(m_szNames));
 	memset(m_MixPlugins, 0, sizeof(m_MixPlugins));
 	ResetMidiCfg();
-	for (UINT npt=0; npt<MAX_PATTERNS; npt++) {
-		PatternSize[npt] = 64;
-		PatternAllocSize[npt] = 64;
-	}
+	for (UINT npt=0; npt<MAX_PATTERNS; npt++) PatternSize[npt] = 64;
 	for (UINT nch=0; nch<MAX_BASECHANNELS; nch++)
 	{
 		ChnSettings[nch].nPan = 128;
@@ -145,15 +137,16 @@
 		BOOL bMMCmp = MMCMP_Unpack(&lpStream, &dwMemLength);
 #endif
 		if ((!ReadXM(lpStream, dwMemLength))
-		 && (!Read669(lpStream, dwMemLength))
 		 && (!ReadS3M(lpStream, dwMemLength))
 		 && (!ReadIT(lpStream, dwMemLength))
 		 && (!ReadWav(lpStream, dwMemLength))
+#ifndef MODPLUG_BASIC_SUPPORT
 		 && (!ReadSTM(lpStream, dwMemLength))
 		 && (!ReadMed(lpStream, dwMemLength))
 		 && (!ReadMTM(lpStream, dwMemLength))
 		 && (!ReadMDL(lpStream, dwMemLength))
 		 && (!ReadDBM(lpStream, dwMemLength))
+		 && (!Read669(lpStream, dwMemLength))
 		 && (!ReadFAR(lpStream, dwMemLength))
 		 && (!ReadAMS(lpStream, dwMemLength))
 		 && (!ReadOKT(lpStream, dwMemLength))
@@ -165,7 +158,7 @@
 		 && (!ReadAMF(lpStream, dwMemLength))
 		 && (!ReadPSM(lpStream, dwMemLength))
 		 && (!ReadMT2(lpStream, dwMemLength))
-		 && (!ReadMID(lpStream, dwMemLength))
+#endif // MODPLUG_BASIC_SUPPORT
 		 && (!ReadMod(lpStream, dwMemLength))) m_nType = MOD_TYPE_NONE;
 #ifdef MMCMP_SUPPORT
 		if (bMMCmp)
@@ -175,6 +168,14 @@
 		}
 #endif
 	}
+	// Adjust song names
+	for (i=0; i<MAX_SAMPLES; i++)
+	{
+		LPSTR p = m_szNames[i];
+		int j = 31;
+		p[j] = 0;
+		while ((j >= 0) && (p[j] == ' ')) p[j--] = 0;
+	}
 	// Adjust channels
 	for (i=0; i<MAX_BASECHANNELS; i++)
 	{
@@ -194,8 +195,19 @@
 		if (pins->pSample)
 		{
 			if (pins->nLoopEnd > pins->nLength) pins->nLoopEnd = pins->nLength;
+			if (pins->nLoopStart + 3 >= pins->nLoopEnd)
+			{
+				pins->nLoopStart = 0;
+				pins->nLoopEnd = 0;
+			}
 			if (pins->nSustainEnd > pins->nLength) pins->nSustainEnd = pins->nLength;
-		} else {
+			if (pins->nSustainStart + 3 >= pins->nSustainEnd)
+			{
+				pins->nSustainStart = 0;
+				pins->nSustainEnd = 0;
+			}
+		} else
+		{
 			pins->nLength = 0;
 			pins->nLoopStart = 0;
 			pins->nLoopEnd = 0;
@@ -209,7 +221,8 @@
 	// Check invalid instruments
 	while ((m_nInstruments > 0) && (!Headers[m_nInstruments])) m_nInstruments--;
 	// Set default values
-	if (m_nDefaultTempo < 31) m_nDefaultTempo = 31;
+	if (m_nSongPreAmp < 0x20) m_nSongPreAmp = 0x20;
+	if (m_nDefaultTempo < 32) m_nDefaultTempo = 125;
 	if (!m_nDefaultSpeed) m_nDefaultSpeed = 6;
 	m_nMusicSpeed = m_nDefaultSpeed;
 	m_nMusicTempo = m_nDefaultTempo;
@@ -238,7 +251,14 @@
 			}
 		}
 	}
-	return m_nType ? TRUE : FALSE;
+	if (m_nType)
+	{
+		UINT maxpreamp = 0x10+(m_nChannels*8);
+		if (maxpreamp > 100) maxpreamp = 100;
+		if (m_nSongPreAmp > maxpreamp) m_nSongPreAmp = maxpreamp;
+		return TRUE;
+	}
+	return FALSE;
 }
 
 
@@ -447,7 +467,6 @@
 	gdwMixingFreq = nRate;
 	gnBitsPerSample = nBits;
 	InitPlayer(bReset);
-//printf("Rate=%u Bits=%u Channels=%u MMX=%u\n",gdwMixingFreq,gnBitsPerSample,gnChannels,bMMX);
 	return TRUE;
 }
 
@@ -475,7 +494,7 @@
 {
 	if (nVol < 1) nVol = 1;
 	if (nVol > 0x200) nVol = 0x200;	// x4 maximum
-	if ((gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC))
+	if ((nVol < m_nMasterVolume) && (nVol) && (gdwSoundSetup & SNDMIX_AGC) && (bAdjustAGC))
 	{
 		gnAGC = gnAGC * m_nMasterVolume / nVol;
 		if (gnAGC > AGC_UNITY) gnAGC = AGC_UNITY;
@@ -678,6 +697,7 @@
 	m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
 }
 
+
 void CSoundFile::ResetChannels()
 //------------------------------
 {
@@ -690,21 +710,6 @@
 }
 
 
-void CSoundFile::ResetTimestamps()
-//--------------------------------
-{
-	int n;
-	
-	for (n = 1; n < MAX_SAMPLES; n++) {
-		Ins[n].played = 0;
-	}
-	for (n = 1; n < MAX_INSTRUMENTS; n++) {
-		if (Headers[n])
-			Headers[n]->played = 0;
-	}
-}
-
-
 void CSoundFile::LoopPattern(int nPat, int nRow)
 //----------------------------------------------
 {
@@ -751,7 +756,7 @@
 	case MOD_TYPE_S3M:	n = MOD_TYPE_S3M;
 	}
 	n |= MOD_TYPE_XM | MOD_TYPE_IT;
-	if (!(m_dwSongFlags & SONG_INSTRUMENTMODE))
+	if (!m_nInstruments)
 	{
 		if (m_nSamples < 32) n |= MOD_TYPE_MOD;
 		n |= MOD_TYPE_S3M;
@@ -850,8 +855,7 @@
 
 #ifndef MODPLUG_NO_FILESAVE
 
-UINT CSoundFile::WriteSample(diskwriter_driver_t *f, MODINSTRUMENT *pins,
-				UINT nFlags, UINT nMaxLen)
+UINT CSoundFile::WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen)
 //-----------------------------------------------------------------------------------
 {
 	UINT len = 0, bufcount;
@@ -869,7 +873,7 @@
 		{
 			int pos;
 			len = (nLen + 1) / 2;
-			f->o(f, (const unsigned char *)CompressionTable, 16);
+			fwrite(CompressionTable, 16, 1, f);
 			bufcount = 0;
 			pos = 0;
 			for (UINT j=0; j<len; j++)
@@ -882,11 +886,11 @@
 				buffer[bufcount++] = (signed char)b;
 				if (bufcount >= sizeof(buffer))
 				{
-					f->o(f, (const unsigned char *)buffer, bufcount);
+					fwrite(buffer, 1, bufcount, f);
 					bufcount = 0;
 				}
 			}
-			if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount);
+			if (bufcount) fwrite(buffer, 1, bufcount, f);
 			len += 16;
 		}
 		break;
@@ -913,20 +917,22 @@
 				}
 				if (nFlags == RS_PCM16D)
 				{
-					*((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new - s_old));
+					short temp = bswapLE16((short)(s_new - s_old));
+					*((short *)(&buffer[bufcount])) = temp;
 					s_old = s_new;
 				} else
 				{
-					*((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new + s_ofs));
+					short temp = bswapLE16((short)(s_new + s_ofs));
+					*((short *)(&buffer[bufcount])) = temp;
 				}
 				bufcount += 2;
 				if (bufcount >= sizeof(buffer) - 1)
 				{
-					f->o(f, (const unsigned char *)buffer, bufcount);
+					fwrite(buffer, 1, bufcount, f);
 					bufcount = 0;
 				}
 			}
-			if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount);
+			if (bufcount) fwrite(buffer, 1, bufcount, f);
 		}
 		break;
 
@@ -957,11 +963,11 @@
 					}
 					if (bufcount >= sizeof(buffer))
 					{
-						f->o(f, (const unsigned char *)buffer, bufcount);
+						fwrite(buffer, 1, bufcount, f);
 						bufcount = 0;
 					}
 				}
-				if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount);
+				if (bufcount) fwrite(buffer, 1, bufcount, f);
 			}
 		}
 		len = nLen * 2;
@@ -985,20 +991,22 @@
 					p += 2;
 					if (nFlags == RS_STPCM16D)
 					{
-						*((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new - s_old));
+						short temp = bswapLE16((short)(s_new - s_old));
+						*((short *)(&buffer[bufcount])) = temp;
 						s_old = s_new;
 					} else
 					{
-						*((short *)(&buffer[bufcount])) = bswapLE16((short)(s_new + s_ofs));
+						short temp = bswapLE16((short)(s_new - s_ofs));
+						*((short *)(&buffer[bufcount])) = temp;
 					}
 					bufcount += 2;
 					if (bufcount >= sizeof(buffer))
 					{
-						f->o(f, (const unsigned char *)buffer, bufcount);
+						fwrite(buffer, 1, bufcount, f);
 						bufcount = 0;
 					}
 				}
-				if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount);
+				if (bufcount) fwrite(buffer, 1, bufcount, f);
 			}
 		}
 		len = nLen*4;
@@ -1008,25 +1016,8 @@
 	case RS_STIPCM8S:
 	case RS_STIPCM16S:
 		len = nLen * 2;
-		if (nFlags == RS_STIPCM16S) {
-			{
-				signed short *p = (signed short *)pSample;
-				bufcount = 0;
-				for (UINT j=0; j<nLen; j++)
-				{
-					*((short *)(&buffer[bufcount])) = *p;
-					bufcount += 2;
-					if (bufcount >= sizeof(buffer))
-					{
-						f->o(f, (const unsigned char *)buffer, bufcount);
-						bufcount = 0;
-					}
-				}
-				if (bufcount) f->o(f, (const unsigned char *)buffer, bufcount);
-			};
-		} else {
-			f->o(f, (const unsigned char *)pSample, len);
-		}
+		if (nFlags == RS_STIPCM16S) len *= 2;
+		fwrite(pSample, 1, len, f);
 		break;
 
 	// Default: assume 8-bit PCM data
@@ -1036,12 +1027,6 @@
 		{
 			signed char *p = pSample;
 			int sinc = (pins->uFlags & CHN_16BIT) ? 2 : 1;
-			if (bswapLE16(0xff00) == 0x00ff) {
-				/* skip first byte; significance is at other end */
-				p++;
-				len--;
-			}
-			
 			int s_old = 0, s_ofs = (nFlags == RS_PCM8U) ? 0x80 : 0;
 			if (pins->uFlags & CHN_16BIT) p++;
 			for (UINT j=0; j<len; j++)
@@ -1063,11 +1048,11 @@
 				}
 				if (bufcount >= sizeof(buffer))
 				{
-					f->o(f, (const unsigned char *)buffer, bufcount);
+					fwrite(buffer, 1, bufcount, f);
 					bufcount = 0;
 				}
 			}
-			if (bufcount) f->o(f,(const unsigned char *)buffer,bufcount);
+			if (bufcount) fwrite(buffer, 1, bufcount, f);
 		}
 	}
 	return len;
@@ -1089,10 +1074,11 @@
 UINT CSoundFile::ReadSample(MODINSTRUMENT *pIns, UINT nFlags, LPCSTR lpMemFile, DWORD dwMemLength)
 //------------------------------------------------------------------------------------------------
 {
-	UINT len = 0, mem = pIns->nLength+6;
+	UINT len = 0, mem;
 
-	if ((!pIns) || (pIns->nLength < 1) || (!lpMemFile)) return 0;
+	if ((!pIns) || (pIns->nLength < 4) || (!lpMemFile)) return 0;
 	if (pIns->nLength > MAX_SAMPLE_LENGTH) pIns->nLength = MAX_SAMPLE_LENGTH;
+	mem = pIns->nLength+6;
 	pIns->uFlags &= ~(CHN_16BIT|CHN_STEREO);
 	if (nFlags & RSF_16BIT)
 	{
@@ -1166,15 +1152,13 @@
 		{
 			len = pIns->nLength * 2;
 			if (len > dwMemLength) break;
-			short *pSample = (short *)pIns->pSample;
-			short *p = (short *)lpMemFile;
-			unsigned short tmp;
+			short int *pSample = (short int *)pIns->pSample;
+			short int *p = (short int *)lpMemFile;
 			int delta16 = 0;
 			for (UINT j=0; j<len; j+=2)
 			{
-				tmp = *((unsigned short *)p++);
-				delta16 += bswapLE16(tmp);
-				*pSample++ = (short) delta16;
+				delta16 += bswapLE16(*p++);
+				*pSample++ = (short int)delta16;
 			}
 		}
 		break;
@@ -1188,7 +1172,7 @@
 			for (UINT j=0; j<len; j+=2)
 			{
 			        *pSample = bswapLE16(*pSample);
-				pSample++;
+				++pSample;
 			}
 		}
 		break;
@@ -1212,15 +1196,12 @@
 
 	// 6: 16-bit unsigned PCM data
 	case RS_PCM16U:
-	        {
+		{
 			len = pIns->nLength * 2;
-			if (len <= dwMemLength) memcpy(pIns->pSample, lpMemFile, len);
+			if (len > dwMemLength) break;
 			short int *pSample = (short int *)pIns->pSample;
-			for (UINT j=0; j<len; j+=2)
-			{
-			        *pSample = bswapLE16(*pSample) - 0x8000;
-				pSample++;
-			}
+			short int *pSrc = (short int *)lpMemFile;
+			for (UINT j=0; j<len; j+=2) *pSample++ = bswapLE16(*(pSrc++)) - 0x8000;
 		}
 		break;
 
@@ -1302,13 +1283,14 @@
 	case RS_IT2158:
 	case RS_IT21516:
 		len = dwMemLength;
-		if (len < 2) break;
+		if (len < 4) break;
 		if ((nFlags == RS_IT2148) || (nFlags == RS_IT2158))
 			ITUnpack8Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT2158));
 		else
 			ITUnpack16Bit(pIns->pSample, pIns->nLength, (LPBYTE)lpMemFile, dwMemLength, (nFlags == RS_IT21516));
 		break;
 
+#ifndef MODPLUG_BASIC_SUPPORT
 #ifndef MODPLUG_FASTSOUNDLIB
 	// 8-bit interleaved stereo samples
 	case RS_STIPCM8S:
@@ -1382,7 +1364,7 @@
 			for (UINT j=0; j<len; j+=2)   // swaparoni!
 			{
 			        *pSampleW = bswapLE16(*pSampleW);
-				*pSampleW++;
+				++pSampleW;
 			}
 		}
 		break;
@@ -1521,6 +1503,7 @@
 
 #endif // MODPLUG_TRACKER
 #endif // !MODPLUG_FASTSOUNDLIB
+#endif // !MODPLUG_BASIC_SUPPORT
 
 	// Default: 8-bit signed PCM data
 	default:
@@ -1560,11 +1543,11 @@
 		// Adjust end of sample
 		if (pIns->uFlags & CHN_STEREO)
 		{
-			pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
-			pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
+			pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0;
+			pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0;
 		} else
 		{
-			pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
+			pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0;
 		}
 		if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
 		{
@@ -1612,11 +1595,12 @@
 		// Adjust end of sample
 		if (pIns->uFlags & CHN_STEREO)
 		{
-			pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = pSample[len*2-2];
-			pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = pSample[len*2-1];
+			pSample[len*2+6] = pSample[len*2+4] = pSample[len*2+2] = pSample[len*2] = 0;
+			pSample[len*2+7] = pSample[len*2+5] = pSample[len*2+3] = pSample[len*2+1] = 0;
+
 		} else
 		{
-			pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = pSample[len-1];
+			pSample[len+4] = pSample[len+3] = pSample[len+2] = pSample[len+1] = pSample[len] = 0;
 		}
 		if ((pIns->uFlags & (CHN_LOOP|CHN_PINGPONGLOOP|CHN_STEREO)) == CHN_LOOP)
 		{
@@ -1641,6 +1625,8 @@
 //-----------------------------------------------------------
 {
 	//---GCCFIX:  Removed assembly.
+	return (DWORD)(8363*pow(2, (transp*128+ftune)/(1536)));
+
 #ifdef MSC_VER
 	const float _fbase = 8363;
 	const float _factor = 1.0f/(12.0f*128.0f);
@@ -1670,8 +1656,6 @@
 	if (derr <= 5) freq -= derr;
 	if (derr >= 995) freq += 1000-derr;
 	return freq;
-#else
-        return (DWORD) (8363.0 * pow(2, (transp * 128.0 + ftune) / 1536.0));
 #endif
 }
 
@@ -1681,6 +1665,8 @@
 //----------------------------------------------
 {
 	//---GCCFIX:  Removed assembly.
+	return int(1536*(log(freq/8363)/log(2)));
+
 #ifdef MSC_VER
 	const float _f1_8363 = 1.0f / 8363.0f;
 	const float _factor = 128 * 12;
@@ -1696,8 +1682,6 @@
 	fistp result
 	}
 	return result;
-#else
-	return (int) (1536.0 * (log(freq / 8363.0) / log(2)));
 #endif
 }
 
@@ -1794,32 +1778,6 @@
 	return FALSE;
 }
 
-UINT CSoundFile::GetHighestUsedChannel()
-//------------------------------
-{
-	UINT highchan = 0;
-
-	for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++)
-	{
-		MODCOMMAND *p = Patterns[ipat];
-		if (p)
-		{
-			UINT jmax = PatternSize[ipat] * m_nChannels;
-			for (UINT j=0; j<jmax; j++, p++)
-			{
-				if ((p->note) && (p->note <= 120))
-				{
-					if ((j % m_nChannels) > highchan)
-						highchan = j % m_nChannels;
-				}
-			}
-		}
-	}
-
-	return highchan;
-}
-
-
 
 #ifndef MODPLUG_FASTSOUNDLIB
 
@@ -1829,7 +1787,7 @@
 	UINT nExt = 0;
 
 	if (!pbIns) return 0;
-	if (m_dwSongFlags & SONG_INSTRUMENTMODE)
+	if (m_nInstruments)
 	{
 		memset(pbIns, 0, MAX_SAMPLES * sizeof(BOOL));
 		for (UINT ipat=0; ipat<MAX_PATTERNS; ipat++)
--- a/src/modplug/sndfile.h	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/sndfile.h	Fri Dec 07 12:13:37 2007 -0600
@@ -5,18 +5,11 @@
  *          Adam Goode       <adam@evdebs.org> (endian and char fixes for PPC)
 */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "diskwriter.h"
+#include "config.h"
 
 #ifndef __SNDFILE_H
 #define __SNDFILE_H
 
-#define MODPLUG_TRACKER	1
-#define MODPLUG_PLAYER	1
-
 #ifdef UNDER_CE
 int _strnicmp(const char *str1,const char *str2, int n);
 #endif
@@ -35,7 +28,7 @@
 #ifdef MODPLUG_FASTSOUNDLIB
 #define MAX_CHANNELS		80
 #else
-#define MAX_CHANNELS		256
+#define MAX_CHANNELS		128
 #endif
 #define MAX_BASECHANNELS	64
 #define MAX_ENVPOINTS		32
@@ -72,6 +65,7 @@
 #define MOD_TYPE_MT2		0x100000
 #define MOD_TYPE_AMF0		0x200000
 #define MOD_TYPE_PSM		0x400000
+#define MOD_TYPE_J2B		0x800000
 #define MOD_TYPE_UMX		0x80000000 // Fake type
 #define MAX_MODTYPE		23
 
@@ -108,8 +102,6 @@
 #define CHN_EXTRALOUD		0x2000000
 #define CHN_REVERB              0x4000000
 #define CHN_NOREVERB		0x8000000
-// used to turn off mute but have it reset later
-#define CHN_NNAMUTE		0x10000000
 
 
 #define ENV_VOLUME              0x0001
@@ -126,7 +118,6 @@
 #define ENV_VOLCARRY		0x0800
 #define ENV_PANCARRY		0x1000
 #define ENV_PITCHCARRY		0x2000
-#define ENV_MUTE		0x4000
 
 #define CMD_NONE                        0
 #define CMD_ARPEGGIO			1
@@ -263,9 +254,6 @@
 #define SONG_SURROUNDPAN	0x4000
 #define SONG_EXFILTERRANGE	0x8000
 #define SONG_AMIGALIMITS	0x10000
-#define SONG_INSTRUMENTMODE	0x20000
-#define SONG_ORDERLOCKED	0x40000
-#define SONG_NOSTEREO		0x80000
 
 // Global Options (Renderer)
 #define SNDMIX_REVERSESTEREO	0x0001
@@ -284,10 +272,7 @@
 #define SNDMIX_ENABLEMMX		0x20000
 #define SNDMIX_NOBACKWARDJUMPS	0x40000
 #define SNDMIX_MAXDEFAULTPAN	0x80000	// Used by the MOD loader
-#define SNDMIX_MUTECHNMODE                0x100000        // Notes are not played on muted channels
-#define SNDMIX_NOSURROUND 0x200000
-#define SNDMIX_NOMIXING	  0x400000	// don't actually do any mixing (values only)
-#define SNDMIX_NORAMPING  0x800000
+
 
 // Reverb Types (GM2 Presets)
 enum {
@@ -317,59 +302,66 @@
 	UINT nSustainStart, nSustainEnd;
 	signed char *pSample;
 	UINT nC4Speed;
-	UINT nPan;
-	UINT nVolume;
-	UINT nGlobalVol;
-	UINT uFlags;
-	int RelativeTone;
-	int nFineTune;
-	UINT nVibType;
-	UINT nVibSweep;
-	UINT nVibDepth;
-	UINT nVibRate;
+	WORD nPan;
+	WORD nVolume;
+	WORD nGlobalVol;
+	WORD uFlags;
+	signed char RelativeTone;
+	signed char nFineTune;
+	BYTE nVibType;
+	BYTE nVibSweep;
+	BYTE nVibDepth;
+	BYTE nVibRate;
 	CHAR name[22];
-	int played; // for note playback dots
 } MODINSTRUMENT;
 
-typedef struct _INSTRUMENTENVELOPE {
-	int Ticks[32];
-	BYTE Values[32];
-	int nNodes;
-	int nLoopStart;
-	int nLoopEnd;
-	int nSustainStart;
-	int nSustainEnd;
-} INSTRUMENTENVELOPE;
-
 
 // Instrument Struct
 typedef struct _INSTRUMENTHEADER
 {
 	UINT nFadeOut;
 	DWORD dwFlags;
-	unsigned int nGlobalVol;
-	unsigned int nPan;
-	unsigned int Keyboard[128];
-	unsigned int NoteMap[128];
-	INSTRUMENTENVELOPE VolEnv;
-	INSTRUMENTENVELOPE PanEnv;
-	INSTRUMENTENVELOPE PitchEnv;
-	unsigned int nNNA;
-	unsigned int nDCT;
-	unsigned int nDNA;
-	unsigned int nPanSwing;
-	unsigned int nVolSwing;
-	unsigned int nIFC;
-	unsigned int nIFR;
-	unsigned int wMidiBank;
-	unsigned int nMidiProgram;
-	unsigned int nMidiChannel;
-	unsigned int nMidiDrumKey;
-	int nPPS;
-	unsigned int nPPC;
+	WORD nGlobalVol;
+	WORD nPan;
+	WORD VolPoints[MAX_ENVPOINTS];
+	WORD PanPoints[MAX_ENVPOINTS];
+	WORD PitchPoints[MAX_ENVPOINTS];
+	BYTE VolEnv[MAX_ENVPOINTS];
+	BYTE PanEnv[MAX_ENVPOINTS];
+	BYTE PitchEnv[MAX_ENVPOINTS];
+	BYTE Keyboard[128];
+	BYTE NoteMap[128];
+
+	BYTE nVolEnv;
+	BYTE nPanEnv;
+	BYTE nPitchEnv;
+	BYTE nVolLoopStart;
+	BYTE nVolLoopEnd;
+	BYTE nVolSustainBegin;
+	BYTE nVolSustainEnd;
+	BYTE nPanLoopStart;
+	BYTE nPanLoopEnd;
+	BYTE nPanSustainBegin;
+	BYTE nPanSustainEnd;
+	BYTE nPitchLoopStart;
+	BYTE nPitchLoopEnd;
+	BYTE nPitchSustainBegin;
+	BYTE nPitchSustainEnd;
+	BYTE nNNA;
+	BYTE nDCT;
+	BYTE nDNA;
+	BYTE nPanSwing;
+	BYTE nVolSwing;
+	BYTE nIFC;
+	BYTE nIFR;
+	WORD wMidiBank;
+	BYTE nMidiProgram;
+	BYTE nMidiChannel;
+	BYTE nMidiDrumKey;
+	signed char nPPS;
+	unsigned char nPPC;
 	CHAR name[32];
 	CHAR filename[12];
-	int played; // for note playback dots
 } INSTRUMENTHEADER;
 
 
@@ -380,7 +372,6 @@
 	signed char * pCurrentSample;
 	DWORD nPos;
 	DWORD nPosLo;	// actually 16-bit
-	unsigned int topnote_offset;
 	LONG nInc;		// 16.16
 	LONG nRightVol;
 	LONG nLeftVol;
@@ -393,10 +384,8 @@
 	DWORD nLoopEnd;
 	LONG nRampRightVol;
 	LONG nRampLeftVol;
-
-	double nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4;
-	double nFilter_A0, nFilter_B0, nFilter_B1;
-
+	LONG nFilter_Y1, nFilter_Y2, nFilter_Y3, nFilter_Y4;
+	LONG nFilter_A0, nFilter_B0, nFilter_B1;
 	LONG nROfs, nLOfs;
 	LONG nRampLength;
 	// Information not used in the mixer
@@ -404,42 +393,37 @@
 	LONG nNewRightVol, nNewLeftVol;
 	LONG nRealVolume, nRealPan;
 	LONG nVolume, nPan, nFadeOutVol;
-	LONG nPeriod, nC4Speed, sample_freq, nPortamentoDest;
+	LONG nPeriod, nC4Speed, nPortamentoDest;
 	INSTRUMENTHEADER *pHeader;
 	MODINSTRUMENT *pInstrument;
-	int nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition;
+	DWORD nVolEnvPosition, nPanEnvPosition, nPitchEnvPosition;
 	DWORD nMasterChn, nVUMeter;
 	LONG nGlobalVol, nInsVol;
 	LONG nFineTune, nTranspose;
 	LONG nPortamentoSlide, nAutoVibDepth;
 	UINT nAutoVibPos, nVibratoPos, nTremoloPos, nPanbrelloPos;
 	// 16-bit members
-	int nVolSwing, nPanSwing;
-
-	// formally 8-bit members
-	unsigned int nNote, nNNA;
-	unsigned int nNewNote, nNewIns, nCommand, nArpeggio;
-	unsigned int nOldVolumeSlide, nOldFineVolUpDown;
-	unsigned int nOldPortaUpDown, nOldFinePortaUpDown;
-	unsigned int nOldPanSlide, nOldChnVolSlide;
-	unsigned int nVibratoType, nVibratoSpeed, nVibratoDepth;
-	unsigned int nTremoloType, nTremoloSpeed, nTremoloDepth;
-	unsigned int nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth;
-	unsigned int nOldCmdEx, nOldVolParam, nOldTempo;
-	unsigned int nOldOffset, nOldHiOffset;
-	unsigned int nCutOff, nResonance;
-	unsigned int nRetrigCount, nRetrigParam;
-	unsigned int nTremorCount, nTremorParam;
-	unsigned int nPatternLoop, nPatternLoopCount;
-	unsigned int nRowNote, nRowInstr;
-	unsigned int nRowVolCmd, nRowVolume;
-	unsigned int nRowCommand, nRowParam;
-	unsigned int nLeftVU, nRightVU;
-	unsigned int nActiveMacro, nLastInstr;
-	unsigned int nTickStart;
-	unsigned int nRealtime;
-	BYTE stupid_gcc_workaround;
-
+	signed short nVolSwing, nPanSwing;
+	// 8-bit members
+	BYTE nNote, nNNA;
+	BYTE nNewNote, nNewIns, nCommand, nArpeggio;
+	BYTE nOldVolumeSlide, nOldFineVolUpDown;
+	BYTE nOldPortaUpDown, nOldFinePortaUpDown;
+	BYTE nOldPanSlide, nOldChnVolSlide;
+	BYTE nVibratoType, nVibratoSpeed, nVibratoDepth;
+	BYTE nTremoloType, nTremoloSpeed, nTremoloDepth;
+	BYTE nPanbrelloType, nPanbrelloSpeed, nPanbrelloDepth;
+	BYTE nOldCmdEx, nOldVolParam, nOldTempo;
+	BYTE nOldOffset, nOldHiOffset;
+	BYTE nCutOff, nResonance;
+	BYTE nRetrigCount, nRetrigParam;
+	BYTE nTremorCount, nTremorParam;
+	BYTE nPatternLoop, nPatternLoopCount;
+	BYTE nRowNote, nRowInstr;
+	BYTE nRowVolCmd, nRowVolume;
+	BYTE nRowCommand, nRowParam;
+	BYTE nLeftVU, nRightVU;
+	BYTE nActiveMacro, nPadding;
 } MODCHANNEL;
 
 
@@ -470,13 +454,12 @@
 class IMixPlugin
 {
 public:
-	virtual ~IMixPlugin() = 0;
 	virtual int AddRef() = 0;
 	virtual int Release() = 0;
 	virtual void SaveAllParameters() = 0;
 	virtual void RestoreAllParameters() = 0;
-	virtual void Process(float *pOutL, float *pOutR, unsigned int nSamples) = 0;
-	virtual void Init(unsigned int nFreq, int bReset) = 0;
+	virtual void Process(float *pOutL, float *pOutR, unsigned long nSamples) = 0;
+	virtual void Init(unsigned long nFreq, int bReset) = 0;
 	virtual void MidiSend(DWORD dwMidiCode) = 0;
 	virtual void MidiCommand(UINT nMidiCh, UINT nMidiProg, UINT note, UINT vol) = 0;
 };
@@ -540,7 +523,7 @@
 } MODMIDICFG, *LPMODMIDICFG;
 
 
-typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned int, unsigned int); // buffer, samples, channels
+typedef VOID (* LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels
 
 
 
@@ -552,11 +535,11 @@
 	static UINT m_nXBassDepth, m_nXBassRange;
 	static UINT m_nReverbDepth, m_nReverbDelay, gnReverbType;
 	static UINT m_nProLogicDepth, m_nProLogicDelay;
+	static UINT m_nStereoSeparation;
 	static UINT m_nMaxMixChannels;
 	static LONG m_nStreamVolume;
 	static DWORD gdwSysInfo, gdwSoundSetup, gdwMixingFreq, gnBitsPerSample, gnChannels;
-	static UINT gnAGC, gnVolumeRampSamples, gnCPUUsage;
-	static UINT gnVULeft, gnVURight;
+	static UINT gnAGC, gnVolumeRampSamples, gnVUMeter, gnCPUUsage;
 	static LPSNDMIXHOOKPROC gpSndMixHook;
 	static PMIXPLUGINCREATEPROC gpMixPluginCreateProc;
 
@@ -568,34 +551,27 @@
 	MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; // Channels settings
 	MODCOMMAND *Patterns[MAX_PATTERNS];				// Patterns
 	WORD PatternSize[MAX_PATTERNS];					// Patterns Lengths
-	WORD PatternAllocSize[MAX_PATTERNS];				// Allocated pattern lengths (for async. resizing/playback)
 	BYTE Order[MAX_ORDERS];							// Pattern Orders
 	MODMIDICFG m_MidiCfg;							// Midi macro config table
 	SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS];		// Mix plugins
 	UINT m_nDefaultSpeed, m_nDefaultTempo, m_nDefaultGlobalVolume;
 	DWORD m_dwSongFlags;							// Song flags SONG_XXXX
-	UINT m_nStereoSeparation;
 	UINT m_nChannels, m_nMixChannels, m_nMixStat, m_nBufferCount;
 	UINT m_nType, m_nSamples, m_nInstruments;
 	UINT m_nTickCount, m_nTotalCount, m_nPatternDelay, m_nFrameDelay;
 	UINT m_nMusicSpeed, m_nMusicTempo;
 	UINT m_nNextRow, m_nRow;
-	UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nLockedPattern,m_nRestartPos;
+	UINT m_nPattern,m_nCurrentPattern,m_nNextPattern,m_nRestartPos;
 	UINT m_nMasterVolume, m_nGlobalVolume, m_nSongPreAmp;
 	UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide;
 	LONG m_nMinPeriod, m_nMaxPeriod, m_nRepeatCount, m_nInitialRepeatCount;
 	DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples;
-	BYTE m_rowHighlightMajor, m_rowHighlightMinor;
+	UINT m_nMaxOrderPosition;
 	UINT m_nPatternNames;
 	LPSTR m_lpszSongComments, m_lpszPatternNames;
 	char m_szNames[MAX_INSTRUMENTS][32];    // changed from CHAR
 	CHAR CompressionTable[16];
 
-	// chaseback
-	int stop_at_order;
-	int stop_at_row;
-	unsigned int stop_at_time;
-
 public:
 	CSoundFile();
 	~CSoundFile();
@@ -603,7 +579,6 @@
 public:
 	BOOL Create(LPCBYTE lpStream, DWORD dwMemLength=0);
 	BOOL Destroy();
-	UINT GetHighestUsedChannel();
 	UINT GetType() const { return m_nType; }
 	UINT GetNumChannels() const;
 	UINT GetLogicalChannels() const { return m_nChannels; }
@@ -658,17 +633,15 @@
 	BOOL ReadAMF(LPCBYTE lpStream, DWORD dwMemLength);
 	BOOL ReadMT2(LPCBYTE lpStream, DWORD dwMemLength);
 	BOOL ReadPSM(LPCBYTE lpStream, DWORD dwMemLength);
+	BOOL ReadJ2B(LPCBYTE lpStream, DWORD dwMemLength);
 	BOOL ReadUMX(LPCBYTE lpStream, DWORD dwMemLength);
-	BOOL ReadMID(LPCBYTE lpStream, DWORD dwMemLength);
 	// Save Functions
 #ifndef MODPLUG_NO_FILESAVE
-	UINT WriteSample(diskwriter_driver_t *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0);
-	BOOL SaveXM(diskwriter_driver_t *f, UINT nPacking=0);
-	BOOL SaveS3M(diskwriter_driver_t *f, UINT nPacking=0);
-	BOOL SaveMod(diskwriter_driver_t *f, UINT nPacking=0);
-#if 0
+	UINT WriteSample(FILE *f, MODINSTRUMENT *pins, UINT nFlags, UINT nMaxLen=0);
+	BOOL SaveXM(LPCSTR lpszFileName, UINT nPacking=0);
+	BOOL SaveS3M(LPCSTR lpszFileName, UINT nPacking=0);
+	BOOL SaveMod(LPCSTR lpszFileName, UINT nPacking=0);
 	BOOL SaveIT(LPCSTR lpszFileName, UINT nPacking=0);
-#endif
 #endif // MODPLUG_NO_FILESAVE
 	// MOD Convert function
 	UINT GetBestSaveFormat() const;
@@ -677,10 +650,6 @@
 	void S3MConvert(MODCOMMAND *m, BOOL bIT) const;
 	void S3MSaveConvert(UINT *pcmd, UINT *pprm, BOOL bIT) const;
 	WORD ModSaveCommand(const MODCOMMAND *m, BOOL bXM) const;
-public:
-	// backhooks :)
-	static void (*_midi_out_note)(int chan, const MODCOMMAND *m);
-	static void (*_midi_out_raw)(unsigned char *,unsigned int, unsigned int);
 
 public:
 	// Real-time sound functions
@@ -709,23 +678,6 @@
 	static void ResetAGC();
 	static void ProcessAGC(int count);
 
-	// Floats
-	static VOID StereoMixToFloat(const int *pSrc, float *pOut1, float *pOut2, UINT nCount);
-	static VOID FloatToStereoMix(const float *pIn1, const float *pIn2, int *pOut, UINT nCount);
-	static VOID MonoMixToFloat(const int *pSrc, float *pOut, UINT nCount);
-	static VOID FloatToMonoMix(const float *pIn, int *pOut, UINT nCount);
-	
-	
-	
-	
-
-	// wee...
-        static void InitializeEQ(BOOL bReset=TRUE);
-        static void SetEQGains(const UINT *pGains, UINT nBands, const UINT *pFreqs=NULL, BOOL bReset=FALSE);    // 0=-12dB, 32=+12dB
-        /*static*/ void EQStereo(int *pbuffer, UINT nCount);
-        /*static*/ void EQMono(int *pbuffer, UINT nCount);
-
-
 	//GCCFIX -- added these functions back in!
 	static BOOL SetWaveConfigEx(BOOL bSurround,BOOL bNoOverSampling,BOOL bReverb,BOOL hqido,BOOL bMegaBass,BOOL bNR,BOOL bEQ);
 	// DSP Effects
@@ -742,9 +694,9 @@
 	BOOL ReadNote();
 	BOOL ProcessRow();
 	BOOL ProcessEffects();
-	UINT GetNNAChannel(UINT nChn);
+	UINT GetNNAChannel(UINT nChn) const;
 	void CheckNNA(UINT nChn, UINT instr, int note, BOOL bForceCut);
-	void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE, BOOL bManual=FALSE);
+	void NoteChange(UINT nChn, int note, BOOL bPorta=FALSE, BOOL bResetEnv=TRUE);
 	void InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE);
 	// Channel Effects
 	void PortamentoUp(MODCHANNEL *pChn, UINT param);
@@ -770,10 +722,8 @@
 	void ExtendedMODCommands(UINT nChn, UINT param);
 	void ExtendedS3MCommands(UINT nChn, UINT param);
 	void ExtendedChannelEffect(MODCHANNEL *, UINT param);
-	void MidiSend(unsigned char *data, unsigned int len, UINT nChn=0, int fake = 0);
-	void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0,
-			UINT note=0, UINT velocity=0, UINT use_instr=0);
-	void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256,int freq=0) const;
+	void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0);
+	void SetupChannelFilter(MODCHANNEL *pChn, BOOL bReset, int flt_modifier=256) const;
 	// Low-Level effect processing
 	void DoFreqSlide(MODCHANNEL *pChn, LONG nFreqSlide);
 	// Global Effects
@@ -801,7 +751,6 @@
 	// Period/Note functions
 	UINT GetNoteFromPeriod(UINT period) const;
 	UINT GetPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const;
-	UINT GetLinearPeriodFromNote(UINT note, int nFineTune, UINT nC4Speed) const;
 	UINT GetFreqFromPeriod(UINT period, UINT nC4Speed, int nPeriodFrac=0) const;
 	// Misc functions
 	MODINSTRUMENT *GetSample(UINT n) { return Ins+n; }
@@ -810,7 +759,9 @@
 	BOOL ITInstrToMPT(const void *p, INSTRUMENTHEADER *penv, UINT trkvers);
 	UINT SaveMixPlugins(FILE *f=NULL, BOOL bUpdate=TRUE);
 	UINT LoadMixPlugins(const void *pData, UINT nLen);
-	void ResetTimestamps(); // for note playback dots
+#ifndef NO_FILTER
+	DWORD CutOffToFrequency(UINT nCutOff, int flt_modifier=256) const; // [0-255] => [1-10KHz]
+#endif
 
 	// Static helper functions
 public:
@@ -958,8 +909,8 @@
 
 #define MIXBUFFERSIZE		512
 #define MIXING_ATTENUATION	4
-#define MIXING_CLIPMIN		(-0x04000000)
-#define MIXING_CLIPMAX		(0x03FFFFFF)
+#define MIXING_CLIPMIN		(-0x08000000)
+#define MIXING_CLIPMAX		(0x07FFFFFF)
 #define VOLUMERAMPPRECISION	12
 #define FADESONGDELAY		100
 #define EQ_BUFFERSIZE		(MIXBUFFERSIZE)
@@ -978,21 +929,75 @@
 #define MOD2XMFineTune(k)	((int)( (signed char)((k)<<4) ))
 #define XM2MODFineTune(k)	((int)( (k>>4)&0x0f ))
 
-// Return (a*b)/c - no divide error
-static inline int _muldiv(int a, int b, int c)
-{
-	return ((unsigned long long) a * (unsigned long long) b ) / c;
-}
+int _muldiv(long a, long b, long c);
+int _muldivr(long a, long b, long c);
 
 
-// Return (a*b+c/2)/c - no divide error
-static inline int _muldivr(int a, int b, int c)
+// Byte swapping functions from the GNU C Library and libsdl
+
+/* Swap bytes in 16 bit value.  */
+#ifdef __GNUC__
+# define bswap_16(x) \
+    (__extension__							      \
+     ({ unsigned short int __bsx = (x);					      \
+        ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8)); }))
+#else
+static __inline unsigned short int
+bswap_16 (unsigned short int __bsx)
 {
-	return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
+  return ((((__bsx) >> 8) & 0xff) | (((__bsx) & 0xff) << 8));
+}
+#endif
+
+/* Swap bytes in 32 bit value.  */
+#ifdef __GNUC__
+# define bswap_32(x) \
+    (__extension__							      \
+     ({ unsigned int __bsx = (x);					      \
+        ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >>  8) |    \
+	 (((__bsx) & 0x0000ff00) <<  8) | (((__bsx) & 0x000000ff) << 24)); }))
+#else
+static __inline unsigned int
+bswap_32 (unsigned int __bsx)
+{
+  return ((((__bsx) & 0xff000000) >> 24) | (((__bsx) & 0x00ff0000) >>  8) |
+	  (((__bsx) & 0x0000ff00) <<  8) | (((__bsx) & 0x000000ff) << 24));
+}
+#endif
+
+#if (defined ARM) && (defined _WIN32_WCE)
+static __inline unsigned short int
+ARM_get16(const void *data)
+{
+	unsigned short int s;
+	memcpy(&s,data,sizeof(s));
+	return s;
 }
 
+static __inline unsigned int
+ARM_get32(const void *data)
+{
+	unsigned int s;
+	memcpy(&s,data,sizeof(s));
+	return s;
+}
 
-#define NEED_BYTESWAP
-#include "headers.h"
+#define bswapLE16(X) ARM_get16(&X)
+#define bswapLE32(X) ARM_get32(&X)
+#define bswapBE16(X) bswap_16(ARM_get16(&X))
+#define bswapBE32(X) bswap_32(ARM_get32(&X))
+
+// From libsdl
+#elif WORDS_BIGENDIAN
+#define bswapLE16(X) bswap_16(X)
+#define bswapLE32(X) bswap_32(X)
+#define bswapBE16(X) (X)
+#define bswapBE32(X) (X)
+#else
+#define bswapLE16(X) (X)
+#define bswapLE32(X) (X)
+#define bswapBE16(X) bswap_16(X)
+#define bswapBE32(X) bswap_32(X)
+#endif
 
 #endif
--- a/src/modplug/sndmix.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/sndmix.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -7,14 +7,18 @@
 #include "stdafx.h"
 #include "sndfile.h"
 
+#ifdef MODPLUG_TRACKER
+#define ENABLE_STEREOVU
+#endif
 
 // Volume ramp length, in 1/10 ms
 #define VOLUMERAMPLEN	146	// 1.46ms = 64 samples at 44.1kHz
 
 // VU-Meter
-#define VUMETER_DECAY		16
+#define VUMETER_DECAY		4
 
 // SNDMIX: These are global flags for playback control
+UINT CSoundFile::m_nStereoSeparation = 128;
 LONG CSoundFile::m_nStreamVolume = 0x8000;
 UINT CSoundFile::m_nMaxMixChannels = 32;
 // Mixing Configuration (SetWaveConfig)
@@ -26,8 +30,7 @@
 // Mixing data initialized in
 UINT CSoundFile::gnAGC = AGC_UNITY;
 UINT CSoundFile::gnVolumeRampSamples = 64;
-UINT CSoundFile::gnVULeft = 0;
-UINT CSoundFile::gnVURight = 0;
+UINT CSoundFile::gnVUMeter = 0;
 UINT CSoundFile::gnCPUUsage = 0;
 LPSNDMIXHOOKPROC CSoundFile::gpSndMixHook = NULL;
 PMIXPLUGINCREATEPROC CSoundFile::gpMixPluginCreateProc = NULL;
@@ -39,15 +42,15 @@
 
 typedef DWORD (MPPASMCALL * LPCONVERTPROC)(LPVOID, int *, DWORD, LPLONG, LPLONG);
 
-extern DWORD MPPASMCALL Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
-extern DWORD MPPASMCALL Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
-extern DWORD MPPASMCALL Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
-extern DWORD MPPASMCALL Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LONG mins[2], LONG maxs[2]);
-extern UINT MPPASMCALL AGC(int *pBuffer, UINT nSamples, UINT nAGC);
-extern VOID MPPASMCALL Dither(int *pBuffer, UINT nSamples, UINT nBits);
-extern VOID MPPASMCALL InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
-extern VOID MPPASMCALL StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
-extern VOID MPPASMCALL MonoFromStereo(int *pMixBuf, UINT nSamples);
+extern DWORD MPPASMCALL X86_Convert32To8(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
+extern DWORD MPPASMCALL X86_Convert32To16(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
+extern DWORD MPPASMCALL X86_Convert32To24(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
+extern DWORD MPPASMCALL X86_Convert32To32(LPVOID lpBuffer, int *, DWORD nSamples, LPLONG, LPLONG);
+extern UINT MPPASMCALL X86_AGC(int *pBuffer, UINT nSamples, UINT nAGC);
+extern VOID MPPASMCALL X86_Dither(int *pBuffer, UINT nSamples, UINT nBits);
+extern VOID MPPASMCALL X86_InterleaveFrontRear(int *pFrontBuf, int *pRearBuf, DWORD nSamples);
+extern VOID MPPASMCALL X86_StereoFill(int *pBuffer, UINT nSamples, LPLONG lpROfs, LPLONG lpLOfs);
+extern VOID MPPASMCALL X86_MonoFromStereo(int *pMixBuf, UINT nSamples);
 
 extern short int ModSinusTable[64];
 extern short int ModRampDownTable[64];
@@ -82,6 +85,104 @@
 };
 
 
+// Return (a*b)/c - no divide error
+int _muldiv(long a, long b, long c)
+{
+#ifdef MSC_VER
+	int sign, result;
+	_asm {
+	mov eax, a
+	mov ebx, b
+	or eax, eax
+	mov edx, eax
+	jge aneg
+	neg eax
+aneg:
+	xor edx, ebx
+	or ebx, ebx
+	mov ecx, c
+	jge bneg
+	neg ebx
+bneg:
+	xor edx, ecx
+	or ecx, ecx
+	mov sign, edx
+	jge cneg
+	neg ecx
+cneg:
+	mul ebx
+	cmp edx, ecx
+	jae diverr
+	div ecx
+	jmp ok
+diverr:
+	mov eax, 0x7fffffff
+ok:
+	mov edx, sign
+	or edx, edx
+	jge rneg
+	neg eax
+rneg:
+	mov result, eax
+	}
+	return result;
+#else
+	return ((unsigned long long) a * (unsigned long long) b ) / c;
+#endif
+}
+
+
+// Return (a*b+c/2)/c - no divide error
+int _muldivr(long a, long b, long c)
+{
+#ifdef MSC_VER
+	int sign, result;
+	_asm {
+	mov eax, a
+	mov ebx, b
+	or eax, eax
+	mov edx, eax
+	jge aneg
+	neg eax
+aneg:
+	xor edx, ebx
+	or ebx, ebx
+	mov ecx, c
+	jge bneg
+	neg ebx
+bneg:
+	xor edx, ecx
+	or ecx, ecx
+	mov sign, edx
+	jge cneg
+	neg ecx
+cneg:
+	mul ebx
+	mov ebx, ecx
+	shr ebx, 1
+	add eax, ebx
+	adc edx, 0
+	cmp edx, ecx
+	jae diverr
+	div ecx
+	jmp ok
+diverr:
+	mov eax, 0x7fffffff
+ok:
+	mov edx, sign
+	or edx, edx
+	jge rneg
+	neg eax
+rneg:
+	mov result, eax
+	}
+	return result;
+#else
+	return ((unsigned long long) a * (unsigned long long) b + (c >> 1)) / c;
+#endif
+}
+
+
 BOOL CSoundFile::InitPlayer(BOOL bReset)
 //--------------------------------------
 {
@@ -94,13 +195,11 @@
 	gnRvbROfsVol = gnRvbLOfsVol = 0;
 	if (bReset)
 	{
-		gnVULeft = 0;
-		gnVURight = 0;
+		gnVUMeter = 0;
 		gnCPUUsage = 0;
 	}
 	gbInitPlugins = (bReset) ? 3 : 1;
 	InitializeDSP(bReset);
-	InitializeEQ(bReset);
 	return TRUE;
 }
 
@@ -146,28 +245,22 @@
 //-------------------------------------------------------
 {
 	LPBYTE lpBuffer = (LPBYTE)lpDestBuffer;
-	LPCONVERTPROC pCvt = Convert32To8;
-	LONG vu_min[2];
-	LONG vu_max[2];
+	LPCONVERTPROC pCvt = X86_Convert32To8;
 	UINT lRead, lMax, lSampleSize, lCount, lSampleCount, nStat=0;
-#if 0
+	LONG nVUMeterMin = 0x7FFFFFFF, nVUMeterMax = -0x7FFFFFFF;
 	UINT nMaxPlugins;
-#endif
 
-	vu_min[0] = vu_min[1] = 0x7FFFFFFF;
-	vu_max[0] = vu_max[1] = -0x7FFFFFFF;
-
-#if 0
 	{
 		nMaxPlugins = MAX_MIXPLUGINS;
 		while ((nMaxPlugins > 0) && (!m_MixPlugins[nMaxPlugins-1].pMixPlugin)) nMaxPlugins--;
 	}
-#endif
 	m_nMixStat = 0;
 	lSampleSize = gnChannels;
-	if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = Convert32To16; }
-	else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = Convert32To24; }
-	else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = Convert32To32; }
+	if (gnBitsPerSample == 16) { lSampleSize *= 2; pCvt = X86_Convert32To16; }
+#ifndef MODPLUG_FASTSOUNDLIB
+	else if (gnBitsPerSample == 24) { lSampleSize *= 3; pCvt = X86_Convert32To24; }
+	else if (gnBitsPerSample == 32) { lSampleSize *= 4; pCvt = X86_Convert32To32; }
+#endif
 	lMax = cbBuffer / lSampleSize;
 	if ((!lMax) || (!lpBuffer) || (!m_nChannels)) return 0;
 	lRead = lMax;
@@ -175,19 +268,26 @@
 	while (lRead > 0)
 	{
 		// Update Channel Data
-		UINT lTotalSampleCount;
 		if (!m_nBufferCount)
 		{
-			if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))
-				m_nBufferCount = lRead;
-			if (!ReadNote()) {
+#ifndef MODPLUG_FASTSOUNDLIB
+			if (m_dwSongFlags & SONG_FADINGSONG)
+			{
 				m_dwSongFlags |= SONG_ENDREACHED;
-				if (stop_at_order > -1) return 0; /* faster */
-				if (lRead == lMax) goto MixDone;
-				if (!(gdwSoundSetup & SNDMIX_DIRECTTODISK))
+				m_nBufferCount = lRead;
+			} else
+#endif
+			if (!ReadNote())
+			{
+#ifndef MODPLUG_FASTSOUNDLIB
+				if (!FadeSong(FADESONGDELAY))
+#endif
+				{
+					m_dwSongFlags |= SONG_ENDREACHED;
+					if (lRead == lMax) goto MixDone;
 					m_nBufferCount = lRead;
+				}
 			}
-			if (!m_nBufferCount) goto MixDone;
 		}
 		lCount = m_nBufferCount;
 		if (lCount > MIXBUFFERSIZE) lCount = MIXBUFFERSIZE;
@@ -197,46 +297,30 @@
 #ifndef MODPLUG_NO_REVERB
 		gnReverbSend = 0;
 #endif
-
 		// Resetting sound buffer
-		StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
+		X86_StereoFill(MixSoundBuffer, lSampleCount, &gnDryROfsVol, &gnDryLOfsVol);
 		if (gnChannels >= 2)
 		{
 			lSampleCount *= 2;
 			m_nMixStat += CreateStereoMix(lCount);
-#if 0
-			if (nMaxPlugins) ProcessPlugins(lCount);
-#endif
 			ProcessStereoDSP(lCount);
 		} else
 		{
 			m_nMixStat += CreateStereoMix(lCount);
-#if 0
-			if (nMaxPlugins) ProcessPlugins(lCount);
-#endif
-			MonoFromStereo(MixSoundBuffer, lCount);
-			ProcessMonoDSP(lCount);
+			ProcessStereoDSP(lCount);
+			X86_MonoFromStereo(MixSoundBuffer, lCount);
 		}
-
-		if (gdwSoundSetup & SNDMIX_EQ)
-		{
-			if (gnChannels >= 2)
-				EQStereo(MixSoundBuffer, lCount);
-			else
-				EQMono(MixSoundBuffer, lCount);
-		}
-
-
 		nStat++;
 #ifndef NO_AGC
 		// Automatic Gain Control
 		if (gdwSoundSetup & SNDMIX_AGC) ProcessAGC(lSampleCount);
 #endif
-		lTotalSampleCount = lSampleCount;
+		UINT lTotalSampleCount = lSampleCount;
+#ifndef MODPLUG_FASTSOUNDLIB
 		// Multichannel
 		if (gnChannels > 2)
 		{
-			InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
+			X86_InterleaveFrontRear(MixSoundBuffer, MixRearBuffer, lSampleCount);
 			lTotalSampleCount *= 2;
 		}
 		// Hook Function
@@ -244,8 +328,9 @@
 		{
 			gpSndMixHook(MixSoundBuffer, lTotalSampleCount, gnChannels);
 		}
+#endif
 		// Perform clipping + VU-Meter
-		lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, vu_min, vu_max);
+		lpBuffer += pCvt(lpBuffer, MixSoundBuffer, lTotalSampleCount, &nVUMeterMin, &nVUMeterMax);
 		// Buffer ready
 		lRead -= lCount;
 		m_nBufferCount -= lCount;
@@ -253,16 +338,10 @@
 MixDone:
 	if (lRead) memset(lpBuffer, (gnBitsPerSample == 8) ? 0x80 : 0, lRead * lSampleSize);
 	// VU-Meter
-	vu_min[0] >>= 18;
-	vu_min[1] >>= 18;
-	vu_max[0] >>= 18;
-	vu_max[1] >>= 18;
-	if (vu_max[0] < vu_min[0]) vu_max[0] = vu_min[0];
-	if (vu_max[1] < vu_min[1]) vu_max[1] = vu_min[1];
-	if ((gnVULeft = (UINT)(vu_max[0] - vu_min[0])) > 0xFF)
-		gnVULeft = 0xFF;
-	if ((gnVURight = (UINT)(vu_max[1] - vu_min[1])) > 0xFF)
-		gnVURight = 0xFF;
+	nVUMeterMin >>= (24-MIXING_ATTENUATION);
+	nVUMeterMax >>= (24-MIXING_ATTENUATION);
+	if (nVUMeterMax < nVUMeterMin) nVUMeterMax = nVUMeterMin;
+	if ((gnVUMeter = (UINT)(nVUMeterMax - nVUMeterMin)) > 0xFF) gnVUMeter = 0xFF;
 	if (nStat) { m_nMixStat += nStat-1; m_nMixStat /= nStat; }
 	return lMax - lRead;
 }
@@ -276,75 +355,77 @@
 //---------------------------
 {
 	if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay)
-        {
+	{
 		m_nPatternDelay = 0;
 		m_nFrameDelay = 0;
 		m_nTickCount = 0;
 		m_nRow = m_nNextRow;
-		
 		// Reset Pattern Loop Effect
-		if (m_nCurrentPattern != m_nNextPattern) {
-			if (m_nLockedPattern < MAX_ORDERS) {
-				m_nCurrentPattern = m_nLockedPattern;
-				if (!(m_dwSongFlags & SONG_ORDERLOCKED))
-					m_nLockedPattern = MAX_ORDERS;
-			} else {
-				m_nCurrentPattern = m_nNextPattern;
-			}
-
-			// Check if pattern is valid
-			if (!(m_dwSongFlags & SONG_PATTERNLOOP))
+		if (m_nCurrentPattern != m_nNextPattern) m_nCurrentPattern = m_nNextPattern;
+		// Check if pattern is valid
+		if (!(m_dwSongFlags & SONG_PATTERNLOOP))
+		{
+			m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
+			if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
+			while (m_nPattern >= MAX_PATTERNS)
 			{
+				// End of song ?
+				if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
+				{
+					//if (!m_nRepeatCount)
+						return FALSE;     //never repeat entire song
+					if (!m_nRestartPos)
+					{
+						m_nMusicSpeed = m_nDefaultSpeed;
+						m_nMusicTempo = m_nDefaultTempo;
+						m_nGlobalVolume = m_nDefaultGlobalVolume;
+						for (UINT i=0; i<MAX_CHANNELS; i++)
+						{
+							Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF;
+							Chn[i].nFadeOutVol = 0;
+							if (i < m_nChannels)
+							{
+								Chn[i].nGlobalVol = ChnSettings[i].nVolume;
+								Chn[i].nVolume = ChnSettings[i].nVolume;
+								Chn[i].nPan = ChnSettings[i].nPan;
+								Chn[i].nPanSwing = Chn[i].nVolSwing = 0;
+								Chn[i].nOldVolParam = 0;
+								Chn[i].nOldOffset = 0;
+								Chn[i].nOldHiOffset = 0;
+								Chn[i].nPortamentoDest = 0;
+								if (!Chn[i].nLength)
+								{
+									Chn[i].dwFlags = ChnSettings[i].dwFlags;
+									Chn[i].nLoopStart = 0;
+									Chn[i].nLoopEnd = 0;
+									Chn[i].pHeader = NULL;
+									Chn[i].pSample = NULL;
+									Chn[i].pInstrument = NULL;
+								}
+							}
+						}
+					}
+//					if (m_nRepeatCount > 0) m_nRepeatCount--;
+					m_nCurrentPattern = m_nRestartPos;
+					m_nRow = 0;
+					if ((Order[m_nCurrentPattern] >= MAX_PATTERNS) || (!Patterns[Order[m_nCurrentPattern]])) return FALSE;
+				} else
+				{
+					m_nCurrentPattern++;
+				}
 				m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
 				if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
-				while (m_nPattern >= MAX_PATTERNS)
-				{
-					// End of song ?
-					if ((m_nPattern == 0xFF) || (m_nCurrentPattern >= MAX_ORDERS))
-					{
-						if (m_nRepeatCount > 0) m_nRepeatCount--;
-						if (!m_nRepeatCount) return FALSE;
-						m_nCurrentPattern = m_nRestartPos;
-						if ((Order[m_nCurrentPattern] >= MAX_PATTERNS)
-						    || (!Patterns[Order[m_nCurrentPattern]]))
-							return FALSE;
-					} else {
-						m_nCurrentPattern++;
-					}
-					m_nPattern = (m_nCurrentPattern < MAX_ORDERS) ? Order[m_nCurrentPattern] : 0xFF;
-					if ((m_nPattern < MAX_PATTERNS) && (!Patterns[m_nPattern])) m_nPattern = 0xFE;
-				}
-				m_nNextPattern = m_nCurrentPattern;
-			} else if (m_nCurrentPattern < 255) {
-				if (m_nRepeatCount > 0) m_nRepeatCount--;
-				if (!m_nRepeatCount) return FALSE;
 			}
-		}
-#ifdef MODPLUG_TRACKER
-		if (m_dwSongFlags & SONG_STEP)
-		{
-			m_dwSongFlags &= ~SONG_STEP;
-			m_dwSongFlags |= SONG_PAUSED;
-		}
-#endif // MODPLUG_TRACKER
-		if (!PatternSize[m_nPattern] || !Patterns[m_nPattern]) {
-			/* okay, this is wrong. allocate the pattern _NOW_ */
-			Patterns[m_nPattern] = AllocatePattern(64,64);
-			PatternSize[m_nPattern] = 64;
-			PatternAllocSize[m_nPattern] = 64;
+			m_nNextPattern = m_nCurrentPattern;
 		}
 		// Weird stuff?
-		if (m_nPattern >= MAX_PATTERNS) return FALSE;
+		if ((m_nPattern >= MAX_PATTERNS) || (!Patterns[m_nPattern])) return FALSE;
 		// Should never happen
-		// ... sure it should: suppose there's a C70 effect before a 64-row pattern.
-		// It's in fact very easy to make this happen ;)
-		//       - chisel
 		if (m_nRow >= PatternSize[m_nPattern]) m_nRow = 0;
-                m_nNextRow = m_nRow + 1;
+		m_nNextRow = m_nRow + 1;
 		if (m_nNextRow >= PatternSize[m_nPattern])
 		{
 			if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1;
-			else if (m_nRepeatCount > 0) return FALSE;
 			m_nNextRow = 0;
 		}
 		// Reset channel values
@@ -352,18 +433,7 @@
 		MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels;
 		for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++, m++)
 		{
-			/* skip realtime copyin */
-			if (pChn->nRealtime) continue;
-
-			// this is where we're going to spit out our midi
-			// commands... ALL WE DO is dump raw midi data to
-			// our super-secret "midi buffer"
-			// -mrsb
-			if (_midi_out_note)
-				_midi_out_note(nChn, m);
-
 			pChn->nRowNote = m->note;
-			if (m->instr) pChn->nLastInstr = m->instr;
 			pChn->nRowInstr = m->instr;
 			pChn->nRowVolCmd = m->volcmd;
 			pChn->nRowVolume = m->vol;
@@ -375,14 +445,6 @@
 			pChn->dwFlags &= ~(CHN_PORTAMENTO | CHN_VIBRATO | CHN_TREMOLO | CHN_PANBRELLO);
 			pChn->nCommand = 0;
 		}
-				
-	} else if (_midi_out_note) {
-		MODCOMMAND *m = Patterns[m_nPattern] + m_nRow * m_nChannels;
-		for (UINT nChn=0; nChn<m_nChannels; nChn++, m++)
-		{
-			/* m==NULL allows schism to receive notification of SDx and Scx commands */
-			_midi_out_note(nChn, 0);
-		}
 	}
 	// Should we process tick0 effects?
 	if (!m_nMusicSpeed) m_nMusicSpeed = 1;
@@ -407,100 +469,33 @@
 BOOL CSoundFile::ReadNote()
 //-------------------------
 {
-	// Checking end of row ?
-	if (m_dwSongFlags & SONG_PAUSED)
-	{
-		/*m_nTickCount = 0;*/
-		if (!m_nMusicSpeed) m_nMusicSpeed = 6;
-		if (!m_nMusicTempo) m_nMusicTempo = 125;
-		m_nPatternDelay = 0;
-		m_nFrameDelay = 0;
-
-		m_dwSongFlags |= SONG_FIRSTTICK;
-		if (m_nTickCount) {
-			m_dwSongFlags &= ~SONG_FIRSTTICK;
-		}
-
-		ProcessEffects();
-		m_nTickCount++;
-		if (m_nTickCount >= m_nMusicSpeed) {
-			m_nTickCount = 0;
-		}
-		if (!ProcessEffects()) return FALSE;
-	} else
-	{
-		if (!ProcessRow()) return FALSE;
-	}
-
-	{ /* handle realtime closures */
-		MODCHANNEL *pChn = Chn;
-		for (UINT nChn=0; nChn<m_nChannels; pChn++, nChn++) {
-			/* reset end of "row" */
-			if (pChn->nRealtime && pChn->nRowNote && (pChn->nTickStart % m_nMusicSpeed) == (m_nTickCount % m_nMusicSpeed)) {
-				pChn->nRealtime = 0;
-				pChn->nRowNote = 0;
-				pChn->nRowInstr = 0;
-				//pChn->nMaster
-				pChn->nRowVolCmd = 0;
-				pChn->nRowVolume = 0;
-				pChn->nRowCommand = 0;
-				pChn->nRowParam = 0;
-				pChn->nTickStart = 0;
-			}
-		}
-	};
-
+	if (!ProcessRow()) return FALSE;
 	////////////////////////////////////////////////////////////////////////////////////
 	m_nTotalCount++;
 	if (!m_nMusicTempo) return FALSE;
 	m_nBufferCount = (gdwMixingFreq * 5 * m_nTempoFactor) / (m_nMusicTempo << 8);
-#ifdef MODPLUG_TRACKER
-	if (m_dwSongFlags & SONG_PAUSED)
-	{
-		m_nBufferCount = gdwMixingFreq / 64; // 1/64 seconds
-	}
-#endif
-
-	// chaseback hoo hah
-	if (stop_at_order > -1 && stop_at_row > -1) {
-		if (stop_at_order <= (signed) m_nCurrentPattern && stop_at_row <= (signed) m_nRow) {
-			return FALSE;
-		}
-	}
-
 	// Master Volume + Pre-Amplification / Attenuation setup
 	DWORD nMasterVol;
 	{
-		int nchn32 = 0;
-		MODCHANNEL *pChn = Chn;	
-		for (UINT nChn=0; nChn<m_nChannels; nChn++, pChn++) {
-			nchn32++;
-		}
-		if (nchn32 < 1) nchn32 = 1;
-		if (nchn32 > 31) nchn32 = 31;
-
+		int nchn32 = (m_nChannels < 32) ? m_nChannels : 31;
+		if ((m_nType & MOD_TYPE_IT) && (m_nInstruments) && (nchn32 < 6)) nchn32 = 6;
 		int realmastervol = m_nMasterVolume;
 		if (realmastervol > 0x80)
 		{
 			realmastervol = 0x80 + ((realmastervol - 0x80) * (nchn32+4)) / 16;
 		}
-
-		DWORD mastervol = (realmastervol * (m_nSongPreAmp)) >> 6;
-//		if (mastervol > 0x200) mastervol = 0x200;
+		UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
+		DWORD mastervol = (realmastervol * (m_nSongPreAmp + 0x10)) >> 6;
+		if (mastervol > 0x200) mastervol = 0x200;
 		if ((m_dwSongFlags & SONG_GLOBALFADE) && (m_nGlobalFadeMaxSamples))
 		{
 			mastervol = _muldiv(mastervol, m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples);
 		}
-
-		UINT attenuation = (gdwSoundSetup & SNDMIX_AGC) ? PreAmpAGCTable[nchn32>>1] : PreAmpTable[nchn32>>1];
-		if (attenuation < 1) attenuation = 1;
-
 		nMasterVol = (mastervol << 7) / attenuation;
 		if (nMasterVol > 0x180) nMasterVol = 0x180;
 	}
 	////////////////////////////////////////////////////////////////////////////////////
 	// Update channels data
-	if (CSoundFile::gdwSoundSetup & SNDMIX_NOMIXING) return TRUE;
 	m_nMixChannels = 0;
 	MODCHANNEL *pChn = Chn;
 	for (UINT nChn=0; nChn<MAX_CHANNELS; nChn++,pChn++)
@@ -511,9 +506,12 @@
 			pChn->nROfs = pChn->nLOfs = 0;
 		}
 		// Check for unused channel
-		if ((nChn >= m_nChannels) && (!pChn->nLength))
+		if ((pChn->dwFlags & CHN_MUTE) || ((nChn >= m_nChannels) && (!pChn->nLength)))
 		{
+			pChn->nVUMeter = 0;
+#ifdef ENABLE_STEREOVU
 			pChn->nLeftVU = pChn->nRightVU = 0;
+#endif
 			continue;
 		}
 		// Reset channel data
@@ -577,33 +575,33 @@
 			if (vol > 0x100) vol = 0x100;
 			vol <<= 6;
 			// Process Envelopes
-			if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+			if (pChn->pHeader)
 			{
 				INSTRUMENTHEADER *penv = pChn->pHeader;
 				// Volume Envelope
-				if ((pChn->dwFlags & CHN_VOLENV) && (penv->VolEnv.nNodes))
+				if ((pChn->dwFlags & CHN_VOLENV) && (penv->nVolEnv))
 				{
 					int envpos = pChn->nVolEnvPosition;
-					UINT pt = penv->VolEnv.nNodes - 1;
-					for (UINT i=0; i<(UINT)(penv->VolEnv.nNodes-1); i++)
+					UINT pt = penv->nVolEnv - 1;
+					for (UINT i=0; i<(UINT)(penv->nVolEnv-1); i++)
 					{
-						if (envpos <= penv->VolEnv.Ticks[i])
+						if (envpos <= penv->VolPoints[i])
 						{
 							pt = i;
 							break;
 						}
 					}
-					int x2 = penv->VolEnv.Ticks[pt];
+					int x2 = penv->VolPoints[pt];
 					int x1, envvol;
 					if (envpos >= x2)
 					{
-						envvol = penv->VolEnv.Values[pt] << 2;
+						envvol = penv->VolEnv[pt] << 2;
 						x1 = x2;
 					} else
 					if (pt)
 					{
-						envvol = penv->VolEnv.Values[pt-1] << 2;
-						x1 = penv->VolEnv.Ticks[pt-1];
+						envvol = penv->VolEnv[pt-1] << 2;
+						x1 = penv->VolPoints[pt-1];
 					} else
 					{
 						envvol = 0;
@@ -612,26 +610,26 @@
 					if (envpos > x2) envpos = x2;
 					if ((x2 > x1) && (envpos > x1))
 					{
-						envvol += ((envpos - x1) * (((int)penv->VolEnv.Values[pt]<<2) - envvol)) / (x2 - x1);
+						envvol += ((envpos - x1) * (((int)penv->VolEnv[pt]<<2) - envvol)) / (x2 - x1);
 					}
 					if (envvol < 0) envvol = 0;
 					if (envvol > 256) envvol = 256;
 					vol = (vol * envvol) >> 8;
 				}
 				// Panning Envelope
-				if ((pChn->dwFlags & CHN_PANENV) && (penv->PanEnv.nNodes))
+				if ((pChn->dwFlags & CHN_PANENV) && (penv->nPanEnv))
 				{
 					int envpos = pChn->nPanEnvPosition;
-					UINT pt = penv->PanEnv.nNodes - 1;
-					for (UINT i=0; i<(UINT)(penv->PanEnv.nNodes-1); i++)
+					UINT pt = penv->nPanEnv - 1;
+					for (UINT i=0; i<(UINT)(penv->nPanEnv-1); i++)
 					{
-						if (envpos <= penv->PanEnv.Ticks[i])
+						if (envpos <= penv->PanPoints[i])
 						{
 							pt = i;
 							break;
 						}
 					}
-					int x2 = penv->PanEnv.Ticks[pt], y2 = penv->PanEnv.Values[pt];
+					int x2 = penv->PanPoints[pt], y2 = penv->PanEnv[pt];
 					int x1, envpan;
 					if (envpos >= x2)
 					{
@@ -640,8 +638,8 @@
 					} else
 					if (pt)
 					{
-						envpan = penv->PanEnv.Values[pt-1];
-						x1 = penv->PanEnv.Ticks[pt-1];
+						envpan = penv->PanEnv[pt-1];
+						x1 = penv->PanPoints[pt-1];
 					} else
 					{
 						envpan = 128;
@@ -716,13 +714,8 @@
 			{
 				switch(m_nTickCount % 3)
 				{
-#if 0
 				case 1:	period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
 				case 2:	period = GetPeriodFromNote(pChn->nNote + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
-#else
-				case 1:	period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio >> 4), pChn->nFineTune, pChn->nC4Speed); break;
-				case 2:	period = GetLinearPeriodFromNote(GetNoteFromPeriod(period) + (pChn->nArpeggio & 0x0F), pChn->nFineTune, pChn->nC4Speed); break;
-#endif
 				}
 			}
 
@@ -733,32 +726,30 @@
 			}
 
 			// Pitch/Filter Envelope
-			int envpitch = 0;
-			if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && (pChn->pHeader)
-			    && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->PitchEnv.nNodes))
+			if ((pChn->pHeader) && (pChn->dwFlags & CHN_PITCHENV) && (pChn->pHeader->nPitchEnv))
 			{
 				INSTRUMENTHEADER *penv = pChn->pHeader;
 				int envpos = pChn->nPitchEnvPosition;
-				UINT pt = penv->PitchEnv.nNodes - 1;
-				for (UINT i=0; i<(UINT)(penv->PitchEnv.nNodes-1); i++)
+				UINT pt = penv->nPitchEnv - 1;
+				for (UINT i=0; i<(UINT)(penv->nPitchEnv-1); i++)
 				{
-					if (envpos <= penv->PitchEnv.Ticks[i])
+					if (envpos <= penv->PitchPoints[i])
 					{
 						pt = i;
 						break;
 					}
 				}
-				int x2 = penv->PitchEnv.Ticks[pt];
-				int x1;
+				int x2 = penv->PitchPoints[pt];
+				int x1, envpitch;
 				if (envpos >= x2)
 				{
-					envpitch = (((int)penv->PitchEnv.Values[pt]) - 32) * 8;
+					envpitch = (((int)penv->PitchEnv[pt]) - 32) * 8;
 					x1 = x2;
 				} else
 				if (pt)
 				{
-					envpitch = (((int)penv->PitchEnv.Values[pt-1]) - 32) * 8;
-					x1 = penv->PitchEnv.Ticks[pt-1];
+					envpitch = (((int)penv->PitchEnv[pt-1]) - 32) * 8;
+					x1 = penv->PitchPoints[pt-1];
 				} else
 				{
 					envpitch = 0;
@@ -767,13 +758,19 @@
 				if (envpos > x2) envpos = x2;
 				if ((x2 > x1) && (envpos > x1))
 				{
-					int envpitchdest = (((int)penv->PitchEnv.Values[pt]) - 32) * 8;
+					int envpitchdest = (((int)penv->PitchEnv[pt]) - 32) * 8;
 					envpitch += ((envpos - x1) * (envpitchdest - envpitch)) / (x2 - x1);
 				}
 				if (envpitch < -256) envpitch = -256;
 				if (envpitch > 256) envpitch = 256;
+				// Filter Envelope: controls cutoff frequency
+				if (penv->dwFlags & ENV_FILTER)
+				{
+#ifndef NO_FILTER
+					SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
+#endif // NO_FILTER
+				} else
 				// Pitch Envelope
-				if (!(penv->dwFlags & ENV_FILTER))
 				{
 					int l = envpitch;
 					if (l < 0)
@@ -863,16 +860,6 @@
 			if ((pChn->pInstrument) && (pChn->pInstrument->nVibDepth))
 			{
 				MODINSTRUMENT *pins = pChn->pInstrument;
-				/* this isn't correct, but its better... */
-
-				if (pins->nVibSweep == 0) {
-					pChn->nAutoVibDepth = pins->nVibDepth << 8;
-				} else {
-					pChn->nAutoVibDepth += pins->nVibSweep;
-					if ((pChn->nAutoVibDepth >> 8) > (int)pins->nVibDepth)
-						pChn->nAutoVibDepth = pins->nVibDepth << 8;
-				}
-#if 0
 				if (pins->nVibSweep == 0)
 				{
 					pChn->nAutoVibDepth = pins->nVibDepth << 8;
@@ -880,7 +867,7 @@
 				{
 					if (m_nType & MOD_TYPE_IT)
 					{
-						pChn->nAutoVibDepth += pins->nVibSweep;
+						pChn->nAutoVibDepth += pins->nVibSweep << 3;
 					} else
 					if (!(pChn->dwFlags & CHN_KEYOFF))
 					{
@@ -889,8 +876,7 @@
 					if ((pChn->nAutoVibDepth >> 8) > pins->nVibDepth)
 						pChn->nAutoVibDepth = pins->nVibDepth << 8;
 				}
-#endif
-				pChn->nAutoVibPos += ((int)pins->nVibRate);
+				pChn->nAutoVibPos += pins->nVibRate;
 				int val;
 				switch(pins->nVibType)
 				{
@@ -911,10 +897,6 @@
 					val = ft2VibratoTable[pChn->nAutoVibPos & 255];
 				}
 				int n =	((val * pChn->nAutoVibDepth) >> 8);
-				// is this right? -mrsb
-				if (!(m_dwSongFlags & SONG_ITOLDEFFECTS))
-					n >>= 1;
-
 				if (m_nType & MOD_TYPE_IT)
 				{
 					int df1, df2;
@@ -957,25 +939,12 @@
 				nPeriodFrac = 0;
 			}
 			UINT freq = GetFreqFromPeriod(period, pChn->nC4Speed, nPeriodFrac);
-
-			// Filter Envelope: controls cutoff frequency
-			if (pChn && pChn->pHeader && pChn->pHeader->dwFlags & ENV_FILTER)
-			{
-#ifndef NO_FILTER
-				SetupChannelFilter(pChn, (pChn->dwFlags & CHN_FILTER) ? FALSE : TRUE, envpitch);
-#endif // NO_FILTER
-			}
-
-#if 0
 			if ((m_nType & MOD_TYPE_IT) && (freq < 256))
 			{
 				pChn->nFadeOutVol = 0;
 				pChn->dwFlags |= CHN_NOTEFADE;
 				pChn->nRealVolume = 0;
 			}
-#endif
-			pChn->sample_freq = freq;
-
 			UINT ninc = _muldiv(freq, 0x10000, gdwMixingFreq);
 			if ((ninc >= 0xFFB0) && (ninc <= 0x10090)) ninc = 0x10000;
 			if (m_nFreqFactor != 128) ninc = (ninc * m_nFreqFactor) >> 7;
@@ -984,7 +953,7 @@
 		}
 
 		// Increment envelope position
-		if ((m_dwSongFlags & SONG_INSTRUMENTMODE) && pChn->pHeader)
+		if (pChn->pHeader)
 		{
 			INSTRUMENTHEADER *penv = pChn->pHeader;
 			// Volume Envelope
@@ -995,13 +964,13 @@
 				// Volume Loop ?
 				if (penv->dwFlags & ENV_VOLLOOP)
 				{
-					int volloopend = penv->VolEnv.Ticks[penv->VolEnv.nLoopEnd];
+					UINT volloopend = penv->VolPoints[penv->nVolLoopEnd];
 					if (m_nType != MOD_TYPE_XM) volloopend++;
 					if (pChn->nVolEnvPosition == volloopend)
 					{
-						pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nLoopStart];
-						if ((penv->VolEnv.nLoopEnd == penv->VolEnv.nLoopStart) && (!penv->VolEnv.Values[penv->VolEnv.nLoopStart])
-						 && ((!(m_nType & MOD_TYPE_XM)) || (penv->VolEnv.nLoopEnd+1 == penv->VolEnv.nNodes)))
+						pChn->nVolEnvPosition = penv->VolPoints[penv->nVolLoopStart];
+						if ((penv->nVolLoopEnd == penv->nVolLoopStart) && (!penv->VolEnv[penv->nVolLoopStart])
+						 && ((!(m_nType & MOD_TYPE_XM)) || (penv->nVolLoopEnd+1 == penv->nVolEnv)))
 						{
 							pChn->dwFlags |= CHN_NOTEFADE;
 							pChn->nFadeOutVol = 0;
@@ -1011,15 +980,15 @@
 				// Volume Sustain ?
 				if ((penv->dwFlags & ENV_VOLSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
 				{
-					if (pChn->nVolEnvPosition == (int)penv->VolEnv.Ticks[penv->VolEnv.nSustainEnd]+1)
-						pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nSustainStart];
+					if (pChn->nVolEnvPosition == (UINT)penv->VolPoints[penv->nVolSustainEnd]+1)
+						pChn->nVolEnvPosition = penv->VolPoints[penv->nVolSustainBegin];
 				} else
 				// End of Envelope ?
-				if (pChn->nVolEnvPosition > penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1])
+				if (pChn->nVolEnvPosition > penv->VolPoints[penv->nVolEnv - 1])
 				{
 					if ((m_nType & MOD_TYPE_IT) || (pChn->dwFlags & CHN_KEYOFF)) pChn->dwFlags |= CHN_NOTEFADE;
-					pChn->nVolEnvPosition = penv->VolEnv.Ticks[penv->VolEnv.nNodes - 1];
-					if ((!penv->VolEnv.Values[penv->VolEnv.nNodes-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT)))
+					pChn->nVolEnvPosition = penv->VolPoints[penv->nVolEnv - 1];
+					if ((!penv->VolEnv[penv->nVolEnv-1]) && ((nChn >= m_nChannels) || (m_nType & MOD_TYPE_IT)))
 					{
 						pChn->dwFlags |= CHN_NOTEFADE;
 						pChn->nFadeOutVol = 0;
@@ -1034,21 +1003,21 @@
 				pChn->nPanEnvPosition++;
 				if (penv->dwFlags & ENV_PANLOOP)
 				{
-					int panloopend = penv->PanEnv.Ticks[penv->PanEnv.nLoopEnd];
+					UINT panloopend = penv->PanPoints[penv->nPanLoopEnd];
 					if (m_nType != MOD_TYPE_XM) panloopend++;
 					if (pChn->nPanEnvPosition == panloopend)
-						pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nLoopStart];
+						pChn->nPanEnvPosition = penv->PanPoints[penv->nPanLoopStart];
 				}
 				// Panning Sustain ?
-				if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (int)penv->PanEnv.Ticks[penv->PanEnv.nSustainEnd]+1)
+				if ((penv->dwFlags & ENV_PANSUSTAIN) && (pChn->nPanEnvPosition == (UINT)penv->PanPoints[penv->nPanSustainEnd]+1)
 				 && (!(pChn->dwFlags & CHN_KEYOFF)))
 				{
 					// Panning sustained
-					pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nSustainStart];
+					pChn->nPanEnvPosition = penv->PanPoints[penv->nPanSustainBegin];
 				} else
 				{
-					if (pChn->nPanEnvPosition > penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1])
-						pChn->nPanEnvPosition = penv->PanEnv.Ticks[penv->PanEnv.nNodes - 1];
+					if (pChn->nPanEnvPosition > penv->PanPoints[penv->nPanEnv - 1])
+						pChn->nPanEnvPosition = penv->PanPoints[penv->nPanEnv - 1];
 				}
 			}
 			// Pitch Envelope
@@ -1059,22 +1028,22 @@
 				// Pitch Loop ?
 				if (penv->dwFlags & ENV_PITCHLOOP)
 				{
-					if (pChn->nPitchEnvPosition >= penv->PitchEnv.Ticks[penv->PitchEnv.nLoopEnd])
-						pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nLoopStart];
+					if (pChn->nPitchEnvPosition >= penv->PitchPoints[penv->nPitchLoopEnd])
+						pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchLoopStart];
 				}
 				// Pitch Sustain ?
 				if ((penv->dwFlags & ENV_PITCHSUSTAIN) && (!(pChn->dwFlags & CHN_KEYOFF)))
 				{
-					if (pChn->nPitchEnvPosition == (int)penv->PitchEnv.Ticks[penv->PitchEnv.nSustainEnd]+1)
-						pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nSustainStart];
+					if (pChn->nPitchEnvPosition == (UINT)penv->PitchPoints[penv->nPitchSustainEnd]+1)
+						pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchSustainBegin];
 				} else
 				{
-					if (pChn->nPitchEnvPosition > penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1])
-						pChn->nPitchEnvPosition = penv->PitchEnv.Ticks[penv->PitchEnv.nNodes - 1];
+					if (pChn->nPitchEnvPosition > penv->PitchPoints[penv->nPitchEnv - 1])
+						pChn->nPitchEnvPosition = penv->PitchPoints[penv->nPitchEnv - 1];
 				}
 			}
 		}
-#if 0
+#ifdef MODPLUG_PLAYER
 		// Limit CPU -> > 80% -> don't ramp
 		if ((gnCPUUsage >= 80) && (!pChn->nRealVolume))
 		{
@@ -1085,10 +1054,14 @@
 		pChn->dwFlags &= ~CHN_VOLUMERAMP;
 		if ((pChn->nRealVolume) || (pChn->nLeftVol) || (pChn->nRightVol))
 			pChn->dwFlags |= CHN_VOLUMERAMP;
+#ifdef MODPLUG_PLAYER
 		// Decrease VU-Meter
 		if (pChn->nVUMeter > VUMETER_DECAY)	pChn->nVUMeter -= VUMETER_DECAY; else pChn->nVUMeter = 0;
+#endif // MODPLUG_PLAYER
+#ifdef ENABLE_STEREOVU
 		if (pChn->nLeftVU > VUMETER_DECAY) pChn->nLeftVU -= VUMETER_DECAY; else pChn->nLeftVU = 0;
 		if (pChn->nRightVU > VUMETER_DECAY) pChn->nRightVU -= VUMETER_DECAY; else pChn->nRightVU = 0;
+#endif
 		// Check for too big nInc
 		if (((pChn->nInc >> 16) + 1) >= (LONG)(pChn->nLoopEnd - pChn->nLoopStart)) pChn->dwFlags &= ~CHN_LOOP;
 		pChn->nNewRightVol = pChn->nNewLeftVol = 0;
@@ -1096,11 +1069,14 @@
 		if (pChn->pCurrentSample)
 		{
 			// Update VU-Meter (nRealVolume is 14-bit)
+#ifdef MODPLUG_PLAYER
 			UINT vutmp = pChn->nRealVolume >> (14 - 8);
 			if (vutmp > 0xFF) vutmp = 0xFF;
 			if (pChn->nVUMeter >= 0x100) pChn->nVUMeter = vutmp;
 			vutmp >>= 1;
 			if (pChn->nVUMeter < vutmp)	pChn->nVUMeter = vutmp;
+#endif // MODPLUG_PLAYER
+#ifdef ENABLE_STEREOVU
 			UINT vul = (pChn->nRealVolume * pChn->nRealPan) >> 14;
 			if (vul > 127) vul = 127;
 			if (pChn->nLeftVU > 127) pChn->nLeftVU = (BYTE)vul;
@@ -1111,6 +1087,7 @@
 			if (pChn->nRightVU > 127) pChn->nRightVU = (BYTE)vur;
 			vur >>= 1;
 			if (pChn->nRightVU < vur) pChn->nRightVU = (BYTE)vur;
+#endif
 #ifdef MODPLUG_TRACKER
 			UINT kChnMasterVol = (pChn->dwFlags & CHN_EXTRALOUD) ? 0x100 : nMasterVol;
 #else
@@ -1126,8 +1103,9 @@
 
 				if (pan < 0) pan = 0;
 				if (pan > 256) pan = 256;
+#ifndef MODPLUG_FASTSOUNDLIB
 				if (gdwSoundSetup & SNDMIX_REVERSESTEREO) pan = 256 - pan;
-				if (m_dwSongFlags & SONG_NOSTEREO) pan = 128;
+#endif
 				LONG realvol = (pChn->nRealVolume * kChnMasterVol) >> (8-1);
 				if (gdwSoundSetup & SNDMIX_SOFTPANNING)
 				{
@@ -1156,7 +1134,6 @@
 			// Check IDO
 			if (gdwSoundSetup & SNDMIX_NORESAMPLING)
 			{
-				pChn->dwFlags &= ~(CHN_HQSRC);
 				pChn->dwFlags |= CHN_NOIDO;
 			} else
 			{
@@ -1174,26 +1151,21 @@
 			pChn->nNewLeftVol >>= MIXING_ATTENUATION;
 			pChn->nRightRamp = pChn->nLeftRamp = 0;
 			// Dolby Pro-Logic Surround
-			if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2) && (gdwSoundSetup & SNDMIX_NOSURROUND) == 0)
-				pChn->nNewLeftVol = -pChn->nNewLeftVol;
+			if ((pChn->dwFlags & CHN_SURROUND) && (gnChannels <= 2)) pChn->nNewLeftVol = - pChn->nNewLeftVol;
 			// Checking Ping-Pong Loops
 			if (pChn->dwFlags & CHN_PINGPONGFLAG) pChn->nInc = -pChn->nInc;
 			// Setting up volume ramp
-			if (!(gdwSoundSetup & SNDMIX_NORAMPING)
-			 && (pChn->dwFlags & CHN_VOLUMERAMP)
+			if ((pChn->dwFlags & CHN_VOLUMERAMP)
 			 && ((pChn->nRightVol != pChn->nNewRightVol)
 			  || (pChn->nLeftVol != pChn->nNewLeftVol)))
 			{
 				LONG nRampLength = gnVolumeRampSamples;
 				LONG nRightDelta = ((pChn->nNewRightVol - pChn->nRightVol) << VOLUMERAMPPRECISION);
 				LONG nLeftDelta = ((pChn->nNewLeftVol - pChn->nLeftVol) << VOLUMERAMPPRECISION);
-#if 0
+#ifndef MODPLUG_FASTSOUNDLIB
 				if ((gdwSoundSetup & SNDMIX_DIRECTTODISK)
 				 || ((gdwSysInfo & (SYSMIX_ENABLEMMX|SYSMIX_FASTCPU))
 				  && (gdwSoundSetup & SNDMIX_HQRESAMPLER) && (gnCPUUsage <= 20)))
-#else
-				if (gdwSoundSetup & SNDMIX_HQRESAMPLER)
-#endif
 				{
 					if ((pChn->nRightVol|pChn->nLeftVol) && (pChn->nNewRightVol|pChn->nNewLeftVol) && (!(pChn->dwFlags & CHN_FASTVOLRAMP)))
 					{
@@ -1202,6 +1174,7 @@
 						if (nRampLength < (LONG)gnVolumeRampSamples) nRampLength = gnVolumeRampSamples;
 					}
 				}
+#endif
 				pChn->nRightRamp = nRightDelta / nRampLength;
 				pChn->nLeftRamp = nLeftDelta / nRampLength;
 				pChn->nRightVol = pChn->nNewRightVol - ((pChn->nRightRamp * nRampLength) >> VOLUMERAMPPRECISION);
@@ -1224,15 +1197,15 @@
 			pChn->nRampRightVol = pChn->nRightVol << VOLUMERAMPPRECISION;
 			pChn->nRampLeftVol = pChn->nLeftVol << VOLUMERAMPPRECISION;
 			// Adding the channel in the channel list
-			if (!(pChn->dwFlags & CHN_MUTE)) {
-				ChnMix[m_nMixChannels++] = nChn;
-				if (m_nMixChannels >= MAX_CHANNELS) break;
-			}
+			ChnMix[m_nMixChannels++] = nChn;
+			if (m_nMixChannels >= MAX_CHANNELS) break;
 		} else
 		{
+#ifdef ENABLE_STEREOVU
 			// Note change but no sample
 			if (pChn->nLeftVU > 128) pChn->nLeftVU = 0;
 			if (pChn->nRightVU > 128) pChn->nRightVU = 0;
+#endif
 			if (pChn->nVUMeter > 0xFF) pChn->nVUMeter = 0;
 			pChn->nLeftVol = pChn->nRightVol = 0;
 			pChn->nLength = 0;
--- a/src/modplug/stdafx.h	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/stdafx.h	Fri Dec 07 12:13:37 2007 -0600
@@ -9,7 +9,6 @@
 #ifndef _STDAFX_H_
 #define _STDAFX_H_
 
-#include "headers.h"
 
 #ifdef MSC_VER
 
@@ -20,9 +19,7 @@
 #include <mmsystem.h>
 #include <stdio.h>
 
-inline void ProcessPlugins(int n) {}
-
-#else
+#elif defined(__x86_64__) || defined(__powerpc64__)
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -39,20 +36,24 @@
 typedef unsigned short WORD;
 typedef unsigned char BYTE;
 typedef unsigned char * LPBYTE;
-#ifdef __cplusplus
 typedef bool BOOL;
-#endif
 typedef char * LPSTR;
 typedef void *  LPVOID;
 typedef int * LPLONG;
 typedef unsigned int * LPDWORD;
 typedef unsigned short * LPWORD;
 typedef const char * LPCSTR;
-typedef long long LONGLONG;
+typedef long LONGLONG;
 typedef void * PVOID;
 typedef void VOID;
 
+inline LONG MulDiv (int a, int b, int c)
+{
+  // if (!c) return 0;
+  return ((unsigned long)a * (unsigned long) b ) / c;
+}
 
+#define MODPLUG_NO_FILESAVE
 #define NO_AGC
 #define LPCTSTR LPCSTR
 #define lstrcpyn strncpy
@@ -63,7 +64,6 @@
 
 #define  GHND   0
 
-#ifdef __cplusplus
 inline signed char * GlobalAllocPtr(unsigned int, size_t size)
 {
   signed char * p = (signed char *) malloc(size);
@@ -72,13 +72,86 @@
   return p;
 }
 
-inline void ProcessPlugins(int) {}
+#define GlobalFreePtr(p) free((void *)(p))
+
+#define strnicmp(a,b,c)		strncasecmp(a,b,c)
+#define wsprintf			sprintf
+
+#ifndef FALSE
+#define FALSE	false
+#endif
+
+#ifndef TRUE
+#define TRUE	true
+#endif
+
+#else
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef signed char CHAR;
+typedef unsigned char UCHAR;
+typedef unsigned char* PUCHAR;
+typedef unsigned short USHORT;
+#if defined(__x86_64__) || defined(__powerpc64__)
+typedef unsigned int ULONG;
+typedef unsigned int UINT;
+typedef unsigned int DWORD;
+typedef int LONG;
+typedef long LONGLONG;
+typedef int * LPLONG;
+typedef unsigned int * LPDWORD;
+#else
+typedef unsigned long ULONG;
+typedef unsigned long UINT;
+typedef unsigned long DWORD;
+typedef long LONG;
+typedef long long LONGLONG;
+typedef long * LPLONG;
+typedef unsigned long * LPDWORD;
+#endif
+typedef unsigned short WORD;
+typedef unsigned char BYTE;
+typedef unsigned char * LPBYTE;
+typedef bool BOOL;
+typedef char * LPSTR;
+typedef void *  LPVOID;
+typedef unsigned short * LPWORD;
+typedef const char * LPCSTR;
+typedef void * PVOID;
+typedef void VOID;
+
+inline LONG MulDiv (long a, long b, long c)
+{
+  // if (!c) return 0;
+  return ((unsigned long long) a * (unsigned long long) b ) / c;
+}
+
+#define MODPLUG_NO_FILESAVE
+#define NO_AGC
+#define LPCTSTR LPCSTR
+#define lstrcpyn strncpy
+#define lstrcpy strcpy
+#define lstrcmp strcmp
+#define WAVE_FORMAT_PCM 1
+//#define ENABLE_EQ
+
+#define  GHND   0
+
+inline signed char * GlobalAllocPtr(unsigned int, size_t size)
+{
+  signed char * p = (signed char *) malloc(size);
+
+  if (p != NULL) memset(p, 0, size);
+  return p;
+}
 
 #define GlobalFreePtr(p) free((void *)(p))
 
 #define strnicmp(a,b,c)		strncasecmp(a,b,c)
 #define wsprintf			sprintf
-#endif
 
 #ifndef FALSE
 #define FALSE	false
--- a/src/modplug/tables.cxx	Fri Dec 07 12:09:16 2007 -0600
+++ b/src/modplug/tables.cxx	Fri Dec 07 12:13:37 2007 -0600
@@ -7,6 +7,10 @@
 #include "stdafx.h"
 #include "sndfile.h"
 
+#ifndef MODPLUG_FASTSOUNDLIB
+//#pragma data_seg(".tables")
+#endif
+
 BYTE ImpulseTrackerPortaVolCmd[16] =
 {
 	0x00, 0x01, 0x04, 0x08, 0x10, 0x20, 0x40, 0x60,