diff src/modplug/load_s3m.cxx @ 2337:107c1fed3d92

Port Schism modplug core.
author "Tony Vroon <chainsaw@gentoo.org>"
date Thu, 24 Jan 2008 12:05:59 +0000
parents 6907fc39b53f
children 0b0609eff29b
line wrap: on
line diff
--- a/src/modplug/load_s3m.cxx	Wed Jan 23 19:37:05 2008 +0100
+++ b/src/modplug/load_s3m.cxx	Thu Jan 24 12:05:59 2008 +0000
@@ -289,14 +289,14 @@
 		{
 			UINT j = bswapLE32(*((LPDWORD)(s+0x10)));
 			if (j > MAX_SAMPLE_LENGTH) j = MAX_SAMPLE_LENGTH;
-			if (j < 4) j = 0;
+			if (j < 2) 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 < 4) j = 0;
+			if (j < 2) j = 0;
 			if (j > Ins[iSmp].nLength) j = Ins[iSmp].nLength;
 			Ins[iSmp].nLoopEnd = j;
 			j = s[0x1C];
@@ -319,11 +319,15 @@
 	// Reading patterns
 	for (UINT iPat=0; iPat<patnum; iPat++)
 	{
-		UINT nInd = ((DWORD)ptr[nins+iPat]) << 4;
-		if (nInd + 0x40 > dwMemLength) continue;
+                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;
 		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);
@@ -383,8 +387,11 @@
 	// Reading samples
 	for (UINT iRaw=1; iRaw<=insnum; iRaw++) if ((Ins[iRaw].nLength) && (insfile[iRaw]))
 	{
-		UINT flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U;
-		if (insflags[iRaw-1] & 4) flags += 5;
+		UINT flags;
+		if (insflags[iRaw-1] & 4)
+			flags = (psfh.version == 1) ? RS_PCM16S : RS_PCM16U;
+		else
+			flags = (psfh.version == 1) ? RS_PCM8S : RS_PCM8U;
 		if (insflags[iRaw-1] & 2) flags |= RSF_STEREO;
 		if (inspack[iRaw-1] == 4) flags = RS_ADPCM4;
 		dwMemPos = insfile[iRaw];
@@ -397,254 +404,3 @@
 }
 
 
-#ifndef MODPLUG_NO_FILESAVE
-#pragma warning(disable:4100)
-
-static BYTE S3MFiller[16] =
-{
-	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80
-};
-
-
-BOOL CSoundFile::SaveS3M(LPCSTR lpszFileName, UINT nPacking)
-//----------------------------------------------------------
-{
-	FILE *f;
-	BYTE header[0x60];
-	UINT nbo,nbi,nbp,i;
-	WORD patptr[128];
-	WORD insptr[128];
-	BYTE buffer[5*1024];
-	S3MSAMPLESTRUCT insex[128];
-
-	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));
-	memcpy(header, m_szNames[0], 0x1C);
-	header[0x1B] = 0;
-	header[0x1C] = 0x1A;
-	header[0x1D] = 0x10;
-	nbo = (GetNumPatterns() + 15) & 0xF0;
-	if (!nbo) nbo = 16;
-	header[0x20] = nbo & 0xFF;
-	header[0x21] = nbo >> 8;
-	nbi = m_nInstruments;
-	if (!nbi) nbi = m_nSamples;
-	if (nbi > 99) nbi = 99;
-	header[0x22] = nbi & 0xFF;
-	header[0x23] = nbi >> 8;
-	nbp = 0;
-	for (i=0; Patterns[i]; i++) { nbp = i+1; if (nbp >= MAX_PATTERNS) break; }
-	for (i=0; i<MAX_ORDERS; i++) if ((Order[i] < MAX_PATTERNS) && (Order[i] >= nbp)) nbp = Order[i] + 1;
-	header[0x24] = nbp & 0xFF;
-	header[0x25] = nbp >> 8;
-	if (m_dwSongFlags & SONG_FASTVOLSLIDES) header[0x26] |= 0x40;
-	if ((m_nMaxPeriod < 20000) || (m_dwSongFlags & SONG_AMIGALIMITS)) header[0x26] |= 0x10;
-	header[0x28] = 0x20;
-	header[0x29] = 0x13;
-	header[0x2A] = 0x02; // Version = 1 => Signed samples
-	header[0x2B] = 0x00;
-	header[0x2C] = 'S';
-	header[0x2D] = 'C';
-	header[0x2E] = 'R';
-	header[0x2F] = 'M';
-	header[0x30] = m_nDefaultGlobalVolume >> 2;
-	header[0x31] = m_nDefaultSpeed;
-	header[0x32] = m_nDefaultTempo;
-	header[0x33] = ((m_nSongPreAmp < 0x20) ? 0x20 : m_nSongPreAmp) | 0x80;	// Stereo
-	header[0x35] = 0xFC;
-	for (i=0; i<32; i++)
-	{
-		if (i < m_nChannels)
-		{
-			UINT tmp = (i & 0x0F) >> 1;
-			header[0x40+i] = (i & 0x10) | ((i & 1) ? 8+tmp : tmp);
-		} else header[0x40+i] = 0xFF;
-	}
-	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) + 0x20;
-	UINT ofs = ofs1;
-
-	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++)
-		{
-			chnpan[i] = 0x20 | (ChnSettings[i].nPan >> 4);
-		}
-		fwrite(chnpan, 0x20, 1, f);
-	}
-	if ((nbi*2+nbp*2) & 0x0F)
-	{
-		fwrite(S3MFiller, 0x10 - ((nbi*2+nbp*2) & 0x0F), 1, f);
-	}
-	ofs1 = ftell(f);
-	fwrite(insex, nbi, 0x50, f);
-	// Packing patterns
-	ofs += nbi*0x50;
-	for (i=0; i<nbp; i++)
-	{
-		WORD len = 64;
-		memset(buffer, 0, sizeof(buffer));
-		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<m_nChannels; j++)
-				{
-					UINT b = j;
-					MODCOMMAND *m = &p[row*m_nChannels+j];
-					UINT note = m->note;
-					UINT volcmd = m->volcmd;
-					UINT vol = m->vol;
-					UINT command = m->command;
-					UINT param = m->param;
-
-					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;
-					if (note < 0xFE) note = (note % 12) + ((note / 12) << 4);
-					if (command == CMD_VOLUME)
-					{
-						command = 0;
-						if (param > 64) param = 64;
-						volcmd = VOLCMD_VOLUME;
-						vol = param;
-					}
-					if (volcmd == VOLCMD_VOLUME) b |= 0x40; else
-					if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; }
-					if (command)
-					{
-						S3MSaveConvert(&command, &param, FALSE);
-						if (command) b |= 0x80;
-					}
-					if (b & 0xE0)
-					{
-						buffer[len++] = b;
-						if (b & 0x20)
-						{
-							buffer[len++] = note;
-							buffer[len++] = m->instr;
-						}
-						if (b & 0x40)
-						{
-							buffer[len++] = vol;
-						}
-						if (b & 0x80)
-						{
-							buffer[len++] = command;
-							buffer[len++] = param;
-						}
-						if (len > sizeof(buffer) - 20) break;
-					}
-				}
-				buffer[len++] = 0;
-				if (len > sizeof(buffer) - 20) break;
-			}
-		}
-		buffer[0] = (len - 2) & 0xFF;
-		buffer[1] = (len - 2) >> 8;
-		len = (len+15) & (~0x0F);
-		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 = (WORD)((DWORD)ofs >> 4);
-		if (pins->pSample)
-		{
-			insex[i-1].type = 1;
-			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 = pins->nC4Speed;
-			else
-				insex[i-1].finetune = TransposeToFrequency(pins->RelativeTone, pins->nFineTune);
-			UINT flags = RS_PCM8U;
-#ifndef NO_PACKING
-			if (nPacking)
-			{
-				if ((!(pins->uFlags & (CHN_16BIT|CHN_STEREO)))
-				 && (CanPackSample((char *)pins->pSample, pins->nLength, nPacking)))
-				{
-					insex[i-1].pack = 4;
-					flags = RS_ADPCM4;
-				}
-			} else
-#endif // NO_PACKING
-			{
-				if (pins->uFlags & CHN_16BIT)
-				{
-					insex[i-1].flags |= 4;
-					flags = RS_PCM16U;
-				}
-				if (pins->uFlags & CHN_STEREO)
-				{
-					insex[i-1].flags |= 2;
-					flags = (pins->uFlags & CHN_16BIT) ? RS_STPCM16U : RS_STPCM8U;
-				}
-			}
-			DWORD len = WriteSample(f, pins, flags);
-			if (len & 0x0F)
-			{
-				fwrite(S3MFiller, 0x10 - (len & 0x0F), 1, f);
-			}
-			ofs += (len + 15) & (~0x0F);
-		} else
-		{
-			insex[i-1].length = 0;
-		}
-	}
-	// Updating parapointers
-	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;
-}
-
-#pragma warning(default:4100)
-#endif // MODPLUG_NO_FILESAVE
-