|
From: <rel...@us...> - 2008-07-25 20:20:22
|
Revision: 216
http://modplug.svn.sourceforge.net/modplug/?rev=216&view=rev
Author: relabsoluness
Date: 2008-07-25 20:20:15 +0000 (Fri, 25 Jul 2008)
Log Message:
-----------
./ Merged module loaders from libmodplug along with some tiny changes; should not affect functionality.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/LOAD_AMF.CPP
trunk/OpenMPT/soundlib/LOAD_DBM.CPP
trunk/OpenMPT/soundlib/LOAD_DMF.CPP
trunk/OpenMPT/soundlib/LOAD_DSM.CPP
trunk/OpenMPT/soundlib/Load_669.cpp
trunk/OpenMPT/soundlib/Load_ams.cpp
trunk/OpenMPT/soundlib/Load_far.cpp
trunk/OpenMPT/soundlib/Load_mdl.cpp
trunk/OpenMPT/soundlib/Load_med.cpp
trunk/OpenMPT/soundlib/Load_mod.cpp
trunk/OpenMPT/soundlib/Load_mt2.cpp
trunk/OpenMPT/soundlib/Load_mtm.cpp
trunk/OpenMPT/soundlib/Load_okt.cpp
trunk/OpenMPT/soundlib/Load_psm.cpp
trunk/OpenMPT/soundlib/Load_ptm.cpp
trunk/OpenMPT/soundlib/Load_s3m.cpp
trunk/OpenMPT/soundlib/Load_stm.cpp
trunk/OpenMPT/soundlib/Load_ult.cpp
trunk/OpenMPT/soundlib/Load_umx.cpp
trunk/OpenMPT/soundlib/Load_wav.cpp
trunk/OpenMPT/soundlib/Load_xm.cpp
trunk/OpenMPT/soundlib/Sndfile.h
trunk/OpenMPT/soundlib/load_j2b.cpp
Modified: trunk/OpenMPT/soundlib/LOAD_AMF.CPP
===================================================================
--- trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,10 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
///////////////////////////////////////////////////
@@ -21,7 +21,7 @@
//#define AMFLOG
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
#pragma pack(1)
@@ -58,7 +58,7 @@
//-------------------------------------------------------------------------------
{
UINT lastinstr = 0;
- UINT nTrkSize = *(USHORT *)pTrack;
+ UINT nTrkSize = LittleEndianW(*(USHORT *)pTrack);
nTrkSize += (UINT)pTrack[2] << 16;
pTrack += 3;
while (nTrkSize--)
@@ -168,7 +168,7 @@
BOOL CSoundFile::ReadAMF(LPCBYTE lpStream, DWORD dwMemLength)
//-----------------------------------------------------------
{
- AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream;
+ const AMFFILEHEADER *pfh = (AMFFILEHEADER *)lpStream;
DWORD dwMemPos;
if ((!lpStream) || (dwMemLength < 2048)) return FALSE;
@@ -203,9 +203,9 @@
psmp->nGlobalVol = 64;
if (psmp->nVolume > 0x40) psmp->nVolume = 0x40;
psmp->nVolume <<= 2;
- psmp->nLength = *((LPDWORD)(lpStream+dwMemPos+25));
- psmp->nLoopStart = *((LPDWORD)(lpStream+dwMemPos+29));
- psmp->nLoopEnd = psmp->nLoopStart + *((LPDWORD)(lpStream+dwMemPos+33));
+ psmp->nLength = LittleEndian(*((LPDWORD)(lpStream+dwMemPos+25)));
+ psmp->nLoopStart = LittleEndian(*((LPDWORD)(lpStream+dwMemPos+29)));
+ psmp->nLoopEnd = psmp->nLoopStart + LittleEndian(*((LPDWORD)(lpStream+dwMemPos+33)));
if ((psmp->nLoopEnd > psmp->nLoopStart) && (psmp->nLoopEnd <= psmp->nLength))
{
psmp->uFlags = CHN_LOOP;
@@ -262,7 +262,7 @@
DWORD sampleseekpos[MAX_SAMPLES];
if ((pfh->szAMF[0] != 'A') || (pfh->szAMF[1] != 'M') || (pfh->szAMF[2] != 'F')
- || (pfh->version < 10) || (pfh->version > 14) || (!pfh->numtracks)
+ || (pfh->version < 10) || (pfh->version > 14) || (!LittleEndianW(pfh->numtracks))
|| (!pfh->numorders) || (pfh->numorders > MAX_PATTERNS)
|| (!pfh->numsamples) || (pfh->numsamples > MAX_SAMPLES)
|| (pfh->numchannels < 4) || (pfh->numchannels > 32))
@@ -313,7 +313,7 @@
Patterns[iOrd].Resize(64);
if (pfh->version >= 14)
{
- Patterns[iOrd].Resize(*(USHORT *)(lpStream+dwMemPos));
+ Patterns[iOrd].Resize(LittleEndianW(*(USHORT *)(lpStream+dwMemPos)));
dwMemPos += 2;
}
ptracks[iOrd] = (USHORT *)(lpStream+dwMemPos);
@@ -331,26 +331,27 @@
dwMemPos += sizeof(AMFSAMPLE);
memcpy(m_szNames[iIns+1], psh->samplename, 32);
memcpy(pins->name, psh->filename, 13);
- pins->nLength = psh->length;
- pins->nC4Speed = psh->c2spd;
+ pins->nLength = LittleEndian(psh->length);
+ pins->nC4Speed = LittleEndianW(psh->c2spd);
pins->nGlobalVol = 64;
pins->nVolume = psh->volume * 4;
if (pfh->version >= 11)
{
- pins->nLoopStart = *(DWORD *)(lpStream+dwMemPos);
- pins->nLoopEnd = *(DWORD *)(lpStream+dwMemPos+4);
+ pins->nLoopStart = LittleEndian(*(DWORD *)(lpStream+dwMemPos));
+ pins->nLoopEnd = LittleEndian(*(DWORD *)(lpStream+dwMemPos+4));
dwMemPos += 8;
} else
{
- pins->nLoopStart = *(WORD *)(lpStream+dwMemPos);
+ pins->nLoopStart = LittleEndianW(*(WORD *)(lpStream+dwMemPos));
pins->nLoopEnd = pins->nLength;
dwMemPos += 2;
}
sampleseekpos[iIns] = 0;
- if ((psh->type) && (psh->offset < dwMemLength-1))
+ if ((psh->type) && (LittleEndian(psh->offset) < dwMemLength-1))
{
- sampleseekpos[iIns] = psh->offset;
- if (psh->offset > maxsampleseekpos) maxsampleseekpos = psh->offset;
+ sampleseekpos[iIns] = LittleEndian(psh->offset);
+ if (LittleEndian(psh->offset) > maxsampleseekpos)
+ maxsampleseekpos = LittleEndian(psh->offset);
if ((pins->nLoopEnd > pins->nLoopStart + 2)
&& (pins->nLoopEnd <= pins->nLength)) pins->uFlags |= CHN_LOOP;
}
@@ -368,7 +369,7 @@
memset(pTrackData, 0, sizeof(pTrackData));
for (UINT iTrack=0; iTrack<realtrackcnt; iTrack++) if (dwMemPos + 3 <= dwMemLength)
{
- UINT nTrkSize = *(USHORT *)(lpStream+dwMemPos);
+ UINT nTrkSize = LittleEndianW(*(USHORT *)(lpStream+dwMemPos));
nTrkSize += (UINT)lpStream[dwMemPos+2] << 16;
if (dwMemPos + nTrkSize * 3 + 3 <= dwMemLength)
{
@@ -384,10 +385,10 @@
Patterns[iPat] = p;
for (UINT iChn=0; iChn<m_nChannels; iChn++)
{
- UINT nTrack = ptracks[iPat][iChn];
+ UINT nTrack = LittleEndianW(ptracks[iPat][iChn]);
if ((nTrack) && (nTrack <= pfh->numtracks))
{
- UINT realtrk = pTrackMap[nTrack-1];
+ UINT realtrk = LittleEndianW(pTrackMap[nTrack-1]);
if (realtrk)
{
realtrk--;
Modified: trunk/OpenMPT/soundlib/LOAD_DBM.CPP
===================================================================
--- trunk/OpenMPT/soundlib/LOAD_DBM.CPP 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/LOAD_DBM.CPP 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,11 @@
/*
- * 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.
+ * This source code is public domain.
*
- * Authors: Olivier Lapicque <oli...@jp...>
+ * Copied to OpenMPT from libmodplug.
+ *
+ * Authors: Olivier Lapicque <oli...@jp...>,
+ * Adam Goode <ad...@ev...> (endian and char fixes for PPC)
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
///////////////////////////////////////////////////////////////
@@ -18,7 +19,7 @@
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
#define DBM_FILE_MAGIC 0x304d4244
#define DBM_ID_NAME 0x454d414e
@@ -99,7 +100,7 @@
BOOL CSoundFile::ReadDBM(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
- DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream;
+ const DBMFILEHEADER *pfh = (DBMFILEHEADER *)lpStream;
DWORD dwMemPos;
UINT nOrders, nSamples, nInstruments, nPatterns;
@@ -152,7 +153,6 @@
nsmp = BigEndianW(pih->sampleno);
psmp = ((nsmp) && (nsmp < MAX_SAMPLES)) ? &Ins[nsmp] : NULL;
memset(penv, 0, sizeof(INSTRUMENTHEADER));
- penv->pTuning = penv->s_DefaultTuning;
memcpy(penv->name, pih->name, 30);
if (psmp)
{
Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP
===================================================================
--- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,10 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
///////////////////////////////////////////////////////
@@ -15,7 +15,7 @@
//#define DMFLOG
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
#pragma pack(1)
@@ -89,7 +89,7 @@
BOOL CSoundFile::ReadDMF(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
- DMFHEADER *pfh = (DMFHEADER *)lpStream;
+ const DMFHEADER *pfh = (DMFHEADER *)lpStream;
DMFINFO *psi;
DMFSEQU *sequ;
DWORD dwMemPos;
@@ -121,7 +121,7 @@
if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit;
if ((psi->infosize >= 8) && (!m_lpszSongComments))
{
- m_lpszSongComments = new CHAR[psi->infosize];
+ m_lpszSongComments = new char[psi->infosize];
if (m_lpszSongComments)
{
for (UINT i=0; i<psi->infosize-1; i++)
Modified: trunk/OpenMPT/soundlib/LOAD_DSM.CPP
===================================================================
--- trunk/OpenMPT/soundlib/LOAD_DSM.CPP 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/LOAD_DSM.CPP 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,10 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
+ *
*/
//////////////////////////////////////////////
Modified: trunk/OpenMPT/soundlib/Load_669.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_669.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_669.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,11 @@
/*
- * 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.
+ * This source code is public domain.
*
- * Authors: Olivier Lapicque <oli...@jp...>
+ * Copied to OpenMPT from libmodplug.
+ *
+ * Authors: Olivier Lapicque <oli...@jp...>,
+ * Adam Goode <ad...@ev...> (endian and char fixes for PPC)
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
////////////////////////////////////////////////////////////
@@ -14,12 +15,12 @@
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
typedef struct tagFILEHEADER669
{
WORD sig; // 'if' or 'JN'
- char songmessage[108]; // Song Message
+ signed char songmessage[108]; // Song Message
BYTE samples; // number of samples (1-64)
BYTE patterns; // number of patterns (1-128)
BYTE restartpos;
@@ -47,15 +48,15 @@
DWORD dwMemPos = 0;
if ((!lpStream) || (dwMemLength < sizeof(FILEHEADER669))) return FALSE;
- if ((pfh->sig != 0x6669) && (pfh->sig != 0x4E4A)) return FALSE;
- b669Ext = (pfh->sig == 0x4E4A) ? TRUE : FALSE;
+ if ((LittleEndianW(pfh->sig) != 0x6669) && (LittleEndianW(pfh->sig) != 0x4E4A)) return FALSE;
+ b669Ext = (LittleEndianW(pfh->sig) == 0x4E4A) ? TRUE : FALSE;
if ((!pfh->samples) || (pfh->samples > 64) || (pfh->restartpos >= 128)
|| (!pfh->patterns) || (pfh->patterns > 128)) return FALSE;
DWORD dontfuckwithme = 0x1F1 + pfh->samples * sizeof(SAMPLE669) + pfh->patterns * 0x600;
if (dontfuckwithme > dwMemLength) return FALSE;
for (UINT ichk=0; ichk<pfh->samples; ichk++)
{
- DWORD len = *((DWORD *)(&psmp[ichk].length));
+ DWORD len = LittleEndian(*((DWORD *)(&psmp[ichk].length)));
dontfuckwithme += len;
}
if (dontfuckwithme > dwMemLength) return FALSE;
@@ -71,9 +72,9 @@
m_nSamples = pfh->samples;
for (UINT nins=1; nins<=m_nSamples; nins++, psmp++)
{
- DWORD len = *((DWORD *)(&psmp->length));
- DWORD loopstart = *((DWORD *)(&psmp->loopstart));
- DWORD loopend = *((DWORD *)(&psmp->loopend));
+ DWORD len = LittleEndian(*((DWORD *)(&psmp->length)));
+ DWORD loopstart = LittleEndian(*((DWORD *)(&psmp->loopstart)));
+ DWORD loopend = LittleEndian(*((DWORD *)(&psmp->loopend)));
if (len > MAX_SAMPLE_LENGTH) len = MAX_SAMPLE_LENGTH;
if ((loopend > len) && (!loopstart)) loopend = 0;
if (loopend > len) loopend = len;
Modified: trunk/OpenMPT/soundlib/Load_ams.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_ams.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_ams.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,10 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
//////////////////////////////////////////////
@@ -13,13 +13,13 @@
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
#pragma pack(1)
typedef struct AMSFILEHEADER
{
- CHAR szHeader[7]; // "Extreme"
+ char szHeader[7]; // "Extreme"
BYTE verlo, verhi; // 0x??,0x01
BYTE chncfg;
BYTE samples;
@@ -107,7 +107,7 @@
dwMemPos += tmp;
}
// Read Pattern Names
- m_lpszPatternNames = new CHAR[pfh->patterns * 32];
+ m_lpszPatternNames = new char[pfh->patterns * 32];
if (!m_lpszPatternNames) return TRUE;
m_nPatternNames = pfh->patterns;
memset(m_lpszPatternNames, 0, m_nPatternNames * 32);
@@ -125,7 +125,7 @@
if (dwMemPos + tmp >= dwMemLength) return TRUE;
if (tmp)
{
- m_lpszSongComments = new CHAR[tmp+1];
+ m_lpszSongComments = new char[tmp+1];
if (!m_lpszSongComments) return TRUE;
memset(m_lpszSongComments, 0, tmp+1);
memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp);
@@ -312,7 +312,7 @@
BOOL CSoundFile::ReadAMS2(LPCBYTE lpStream, DWORD dwMemLength)
//------------------------------------------------------------
{
- AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream;
+ const AMS2FILEHEADER *pfh = (AMS2FILEHEADER *)lpStream;
AMS2SONGHEADER *psh;
DWORD dwMemPos;
BYTE smpmap[16];
@@ -356,7 +356,6 @@
if (!penv) return TRUE;
memset(smpmap, 0, sizeof(smpmap));
memset(penv, 0, sizeof(INSTRUMENTHEADER));
- penv->pTuning = penv->s_DefaultTuning;
for (UINT ismpmap=0; ismpmap<pins->samples; ismpmap++)
{
if ((ismpmap >= 16) || (m_nSamples+1 >= MAX_SAMPLES)) break;
@@ -434,7 +433,7 @@
UINT composernamelen = lpStream[dwMemPos];
if (composernamelen)
{
- m_lpszSongComments = new CHAR[composernamelen+1];
+ m_lpszSongComments = new char[composernamelen+1];
if (m_lpszSongComments)
{
memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen);
@@ -485,7 +484,7 @@
{
if ((patnamlen) && (patnamlen < MAX_PATTERNNAME))
{
- CHAR s[MAX_PATTERNNAME];
+ char s[MAX_PATTERNNAME];
memcpy(s, lpStream+dwMemPos+3, patnamlen);
s[patnamlen] = 0;
SetPatternName(ipat, s);
@@ -565,16 +564,16 @@
void AMSUnpack(const char *psrc, UINT inputlen, char *pdest, UINT dmax, char packcharacter)
{
UINT tmplen = dmax;
- char *amstmp = new char[tmplen];
+ signed char *amstmp = new signed char[tmplen];
if (!amstmp) return;
// Unpack Loop
{
- char *p = amstmp;
+ signed char *p = amstmp;
UINT i=0, j=0;
while ((i < inputlen) && (j < tmplen))
{
- char ch = psrc[i++];
+ signed char ch = psrc[i++];
if (ch == packcharacter)
{
BYTE ch2 = psrc[i++];
@@ -592,7 +591,7 @@
}
// Bit Unpack Loop
{
- char *p = amstmp;
+ signed char *p = amstmp;
UINT bitcount = 0x80, dh;
UINT k=0;
for (UINT i=0; i<dmax; i++)
@@ -616,12 +615,12 @@
}
// Delta Unpack
{
- char old = 0;
+ signed char old = 0;
for (UINT i=0; i<dmax; i++)
{
int pos = ((LPBYTE)pdest)[i];
if ((pos != 128) && (pos & 0x80)) pos = -(pos & 0x7F);
- old -= (char)pos;
+ old -= (signed char)pos;
pdest[i] = old;
}
}
Modified: trunk/OpenMPT/soundlib/Load_far.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_far.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_far.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,10 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
////////////////////////////////////////
@@ -13,7 +13,7 @@
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
#define FARFILEMAGIC 0xFE524146 // "FAR"
@@ -61,15 +61,21 @@
BOOL CSoundFile::ReadFAR(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
- FARHEADER1 *pmh1 = (FARHEADER1 *)lpStream;
+ if(dwMemLength < sizeof(FARHEADER1))
+ return FALSE;
+
+ FARHEADER1 farHeader;
+ memcpy(&farHeader, lpStream, sizeof(FARHEADER1));
+ FARHEADER1 *pmh1 = &farHeader;
FARHEADER2 *pmh2;
DWORD dwMemPos = sizeof(FARHEADER1);
UINT headerlen;
BYTE samplemap[8];
- if ((!lpStream) || (dwMemLength < 1024) || (pmh1->id != FARFILEMAGIC)
+ if ((!lpStream) || (dwMemLength < 1024) || (LittleEndian(pmh1->id) != FARFILEMAGIC)
|| (pmh1->magic2[0] != 13) || (pmh1->magic2[1] != 10) || (pmh1->magic2[2] != 26)) return FALSE;
- headerlen = pmh1->headerlen;
+ headerlen = LittleEndianW(pmh1->headerlen);
+ pmh1->stlen = LittleEndianW( pmh1->stlen ); /* inplace byteswap -- Toad */
if ((headerlen >= dwMemLength) || (dwMemPos + pmh1->stlen + sizeof(FARHEADER2) >= dwMemLength)) return FALSE;
// Globals
m_nType = MOD_TYPE_FAR;
@@ -80,6 +86,7 @@
m_nDefaultSpeed = pmh1->speed;
m_nDefaultTempo = 80;
m_nDefaultGlobalVolume = 256;
+
memcpy(m_szNames[0], pmh1->songname, 32);
// Channel Setting
for (UINT nchpan=0; nchpan<16; nchpan++)
@@ -101,7 +108,10 @@
dwMemPos += pmh1->stlen;
}
// Reading orders
- pmh2 = (FARHEADER2 *)(lpStream + dwMemPos);
+ if (sizeof(FARHEADER2) > dwMemLength - dwMemPos) return TRUE;
+ FARHEADER2 farHeader2;
+ memcpy(&farHeader2, lpStream + dwMemPos, sizeof(FARHEADER2));
+ pmh2 = &farHeader2;
dwMemPos += sizeof(FARHEADER2);
if (dwMemPos >= dwMemLength) return TRUE;
for (UINT iorder=0; iorder<MAX_ORDERS; iorder++)
@@ -112,6 +122,14 @@
// Reading Patterns
dwMemPos += headerlen - (869 + pmh1->stlen);
if (dwMemPos >= dwMemLength) return TRUE;
+
+ // byteswap pattern data.
+ for(uint16 psfix = 256; psfix--;)
+ {
+ pmh2->patsiz[psfix] = LittleEndianW( pmh2->patsiz[psfix] ) ;
+ }
+ // end byteswap of pattern data
+
WORD *patsiz = (WORD *)pmh2->patsiz;
for (UINT ipat=0; ipat<256; ipat++) if (patsiz[ipat])
{
@@ -228,13 +246,14 @@
for (UINT ismp=0; ismp<64; ismp++, pins++) if (samplemap[ismp >> 3] & (1 << (ismp & 7)))
{
if (dwMemPos + sizeof(FARSAMPLE) > dwMemLength) return TRUE;
- FARSAMPLE *pfs = (FARSAMPLE *)(lpStream + dwMemPos);
+ const FARSAMPLE *pfs = reinterpret_cast<const FARSAMPLE*>(lpStream + dwMemPos);
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;
+ const DWORD length = LittleEndian( pfs->length );
+ pins->nLength = length;
+ pins->nLoopStart = LittleEndian(pfs->reppos) ;
+ pins->nLoopEnd = LittleEndian(pfs->repend) ;
pins->nFineTune = 0;
pins->nC4Speed = 8363*2;
pins->nGlobalVol = 64;
@@ -253,7 +272,7 @@
ReadSample(pins, (pins->uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S,
(LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
}
- dwMemPos += pfs->length;
+ dwMemPos += length;
}
return TRUE;
}
Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mdl.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,9 +1,8 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
*/
@@ -15,7 +14,7 @@
//#define MDL_LOG
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
typedef struct MDLSONGHEADER
{
@@ -328,7 +327,6 @@
if ((Headers[nins] = new INSTRUMENTHEADER) == NULL) break;
INSTRUMENTHEADER *penv = Headers[nins];
memset(penv, 0, sizeof(INSTRUMENTHEADER));
- penv->pTuning = penv->s_DefaultTuning;
memcpy(penv->name, lpStream+dwPos+2, 32);
penv->nGlobalVol = 64;
penv->nPPC = 5*12;
Modified: trunk/OpenMPT/soundlib/Load_med.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_med.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_med.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,10 @@
/*
- * 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.
+ * This source code is public domain.
*
- * Authors: Olivier Lapicque <oli...@jp...>
+ * Copied to OpenMPT from libmodplug.
+ *
+ * Authors: Olivier Lapicque <oli...@jp...>,
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
#include "stdafx.h"
@@ -493,7 +493,7 @@
// Check for 'MMDx'
DWORD dwSong = BigEndian(pmmh->song);
if ((dwSong >= dwMemLength) || (dwSong + sizeof(MMD0SONGHEADER) >= dwMemLength)) return FALSE;
- version = (char)((pmmh->id >> 24) & 0xFF);
+ version = (signed char)((pmmh->id >> 24) & 0xFF);
if ((version < '0') || (version > '3')) return FALSE;
#ifdef MED_LOG
Log("\nLoading MMD%c module (flags=0x%02X)...\n", version, BigEndian(pmmh->mmdflags));
@@ -699,7 +699,7 @@
UINT annotxt = BigEndian(pmex->annotxt);
UINT annolen = BigEndian(pmex->annolen);
annolen = min(annolen, MED_MAX_COMMENT_LENGTH); //Thanks to Luigi Auriemma for pointing out an overflow risk
- if ((annotxt) && (annolen) && (annotxt+annolen <= dwMemLength) ) {
+ if ((annotxt) && (annolen) && (annolen <= dwMemLength) && (annotxt <= dwMemLength - annolen) ) {
m_lpszSongComments = new char[annolen+1];
if (m_lpszSongComments) {
memcpy(m_lpszSongComments, lpStream+annotxt, annolen);
Modified: trunk/OpenMPT/soundlib/Load_mod.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mod.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_mod.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,16 +1,17 @@
/*
- * 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.
+ * This source code is public domain.
*
- * Authors: Olivier Lapicque <oli...@jp...>
+ * Copied to OpenMPT from libmodplug.
+ *
+ * Authors: Olivier Lapicque <oli...@jp...>,
+ * Adam Goode <ad...@ev...> (endian and char fixes for PPC)
+ * OpenMPT dev(s) (miscellaneous modifications)
*/
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
extern WORD ProTrackerPeriodTable[6*12];
@@ -98,7 +99,7 @@
command = 0x08;
if (bXM)
{
- if ((m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)) && (m_nType != MOD_TYPE_XM) && (param <= 0x80))
+ if (!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)) && (m_nType != MOD_TYPE_XM) && (param <= 0x80))
{
param <<= 1;
if (param > 255) param = 255;
@@ -170,7 +171,7 @@
BYTE nOrders;
BYTE nRestartPos;
BYTE Orders[128];
- CHAR Magic[4];
+ char Magic[4];
} MODMAGIC, *PMODMAGIC;
#pragma pack()
@@ -184,7 +185,7 @@
BOOL CSoundFile::ReadMod(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
- CHAR s[1024];
+ char s[1024];
DWORD dwMemPos, dwTotalSampleLen;
PMODMAGIC pMagic;
UINT nErr;
Modified: trunk/OpenMPT/soundlib/Load_mt2.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mt2.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_mt2.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -250,7 +250,7 @@
{
DWORD nTxtLen = dwLen;
if (nTxtLen > 32000) nTxtLen = 32000;
- m_lpszSongComments = new CHAR[nTxtLen];
+ m_lpszSongComments = new char[nTxtLen];
if (m_lpszSongComments)
{
memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1);
@@ -405,7 +405,6 @@
if (penv)
{
memset(penv, 0, sizeof(INSTRUMENTHEADER));
- penv->pTuning = penv->s_DefaultTuning;
memcpy(penv->name, pmi->szName, 32);
penv->nGlobalVol = 64;
penv->nPan = 128;
Modified: trunk/OpenMPT/soundlib/Load_mtm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mtm.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_mtm.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,16 +1,16 @@
/*
- * 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.
+ * This source code is public domain.
*
+ * Copied to OpenMPT from libmodplug.
+ *
* Authors: Olivier Lapicque <oli...@jp...>
+ *
*/
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
//////////////////////////////////////////////////////////
// MTM file support (import only)
@@ -19,7 +19,7 @@
typedef struct tagMTMSAMPLE
{
- CHAR samplename[22];
+ char samplename[22];
DWORD length;
DWORD reppos;
DWORD repend;
@@ -31,8 +31,8 @@
typedef struct tagMTMHEADER
{
- CHAR id[4]; // MTM file marker + version
- CHAR songname[20]; // ASCIIZ songname
+ char id[4]; // MTM file marker + version
+ char songname[20]; // ASCIIZ songname
WORD numtracks; // number of tracks saved
BYTE lastpattern; // last pattern number saved
BYTE lastorder; // last order number to play (songlength-1)
Modified: trunk/OpenMPT/soundlib/Load_okt.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_okt.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_okt.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,10 +1,11 @@
/*
- * 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.
+ * This source code is public domain.
*
- * Authors: Olivier Lapicque <oli...@jp...>
+ * Copied to OpenMPT from libmodplug.
+ *
+ * Authors: Olivier Lapicque <oli...@jp...>,
+ * Adam Goode <ad...@ev...> (endian and char fixes for PPC)
+ *
*/
//////////////////////////////////////////////
@@ -13,7 +14,7 @@
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244)
+#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
typedef struct OKTFILEHEADER
{
Modified: trunk/OpenMPT/soundlib/Load_psm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_psm.cpp 2008-07-11 16:17:21 UTC (rev 215)
+++ trunk/OpenMPT/soundlib/Load_psm.cpp 2008-07-25 20:20:15 UTC (rev 216)
@@ -1,8 +1,5 @@
/*
- * 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.
+ * This source code is public domain.
*
* Authors: Olivier Lapicque <oli...@jp...>
*/
Modified: trunk/OpenMPT/soundlib/Load_ptm.cpp
================================================...
[truncated message content] |
|
From: <sag...@us...> - 2009-07-11 19:18:34
|
Revision: 292
http://modplug.svn.sourceforge.net/modplug/?rev=292&view=rev
Author: saga-games
Date: 2009-07-11 19:18:24 +0000 (Sat, 11 Jul 2009)
Log Message:
-----------
[Fix] Tremor: Two (not too important) lines were missing
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/Sndfile.cpp
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2009-07-11 18:53:31 UTC (rev 291)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-07-11 19:18:24 UTC (rev 292)
@@ -985,8 +985,6 @@
if (pifh->tempo) m_nDefaultTempo = pifh->tempo;
if(m_nDefaultTempo < 32) m_nDefaultTempo = 32; // tempo 31 is possible. due to conflicts with the rest of the engine, let's just clamp it to 32.
- if(m_nDefaultTempo < 32) m_nDefaultTempo = 32; // tempo 31 is possible. due to conflicts with the rest of the engine, let's just clamp it to 32.
-
m_nSamplePreAmp = pifh->mv & 0x7F;
if (m_nSamplePreAmp<0x20) {
m_nSamplePreAmp=100;
Modified: trunk/OpenMPT/soundlib/Sndfile.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-07-11 18:53:31 UTC (rev 291)
+++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-07-11 19:18:24 UTC (rev 292)
@@ -1135,7 +1135,7 @@
Chn[j].nCommand = 0;
Chn[j].nPatternLoopCount = 0;
Chn[j].nPatternLoop = 0;
- Chn[j].nTremorCount = 0;
+ if(!GetModFlag(MSF_COMPATIBLE_PLAY)) Chn[j].nTremorCount = 0;
}
if (!nPos)
{
@@ -1395,7 +1395,7 @@
Chn[i].nPatternLoop = 0;
Chn[i].nFadeOutVol = 0;
Chn[i].dwFlags |= CHN_KEYOFF|CHN_NOTEFADE;
- Chn[i].nTremorCount = 0;
+ Chn[i].nTremorCount = Chn[i].nTremorOn = Chn[i].nTremorOff = 0;
}
if(resetMask & 4)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-07-26 23:50:27
|
Revision: 305
http://modplug.svn.sourceforge.net/modplug/?rev=305&view=rev
Author: saga-games
Date: 2009-07-26 23:50:13 +0000 (Sun, 26 Jul 2009)
Log Message:
-----------
[Imp] Mod Compatibility: Moved loop length check from compatibility export to normal save, as it does not break/change any MPT-made MOD file.
[Fix] Mod Specifications: Accidentally changed a wrong value in revision 304
[Fix] IT Compatibility: Unbreaking compatible retrigger (line was missing)
Revision Links:
--------------
http://modplug.svn.sourceforge.net/modplug/?rev=304&view=rev
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_mod.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/mod_specifications.h
Modified: trunk/OpenMPT/soundlib/Load_mod.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mod.cpp 2009-07-26 21:59:23 UTC (rev 304)
+++ trunk/OpenMPT/soundlib/Load_mod.cpp 2009-07-26 23:50:13 UTC (rev 305)
@@ -419,7 +419,7 @@
bTab[26] = pins->nLoopStart >> 9;
bTab[27] = pins->nLoopStart >> 1;
UINT replen = pins->nLoopEnd - pins->nLoopStart;
- if(bCompatibilityExport && replen < 2) // ensure PT will load it properly
+ if(replen < 2) // ensure PT will load it properly
replen = 2;
bTab[28] = replen >> 9;
bTab[29] = replen >> 1;
@@ -504,7 +504,7 @@
for (UINT ismpd=1; ismpd<=31; ismpd++) if (inslen[ismpd])
{
MODINSTRUMENT *pins = &Ins[insmap[ismpd]];
- if(bCompatibilityExport == true)
+ if(bCompatibilityExport == true) // first two bytes have to be 0 due to PT's one-shot loop ("no loop")
{
if(pins->nLength > 0) pins->pSample[0] = 0;
if(pins->nLength > 1) pins->pSample[1] = 0;
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-07-26 21:59:23 UTC (rev 304)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-07-26 23:50:13 UTC (rev 305)
@@ -1569,6 +1569,9 @@
if(GetModFlag(MSF_COMPATIBLE_PLAY) && (m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)))
{
//IT compatibility 15. Retrigger
+ if (param)
+ pChn->nRetrigParam = (BYTE)(param & 0xFF);
+
if (volcmd == VOLCMD_OFFSET)
RetrigNote(nChn, pChn->nRetrigParam, vol << 3);
else if (volcmd == VOLCMD_VELOCITY)
Modified: trunk/OpenMPT/soundlib/mod_specifications.h
===================================================================
--- trunk/OpenMPT/soundlib/mod_specifications.h 2009-07-26 21:59:23 UTC (rev 304)
+++ trunk/OpenMPT/soundlib/mod_specifications.h 2009-07-26 23:50:13 UTC (rev 305)
@@ -157,7 +157,7 @@
false, //No notecut.
true, //Has noteoff.
240, //Pattern max.
- 255, //Order max.
+ 256, //Order max.
4, //Channel min
127, //Channel max
32, //Min tempo
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-07-28 13:35:10
|
Revision: 308
http://modplug.svn.sourceforge.net/modplug/?rev=308&view=rev
Author: saga-games
Date: 2009-07-28 13:34:18 +0000 (Tue, 28 Jul 2009)
Log Message:
-----------
[Fix] S3M Saving: Patterns are now saved correctly. Previously, the last few rows might have come up as garbage in ST3, especially (only?) when they were empty.
[Imp] S3M Saving: Using an own version number in the header now, just like all the other trackers.
[Fix] IT Compatibility: Pattern loop count won't be reset on pattern transition (fixes gm-trippy01.it)
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_s3m.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_s3m.cpp 2009-07-27 21:02:38 UTC (rev 307)
+++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2009-07-28 13:34:18 UTC (rev 308)
@@ -12,6 +12,9 @@
#include "sndfile.h"
#include "../mptrack/moddoc.h"
#include "../mptrack/misc_util.h"
+#ifndef MODPLUG_NO_FILESAVE
+#include "../mptrack/version.h"
+#endif
#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
@@ -509,8 +512,13 @@
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;
+
+ // Version info following: ST3.20 = 0x1320
+ // Most significant nibble: 1 = ST3, 2 = Orpheus, 3 = IT, 4 = Schism, 5 = MPT
+ // Following: One nibble = Major version, one byte = Minor version
+ MptVersion::VersionNum vVersion = MptVersion::num;
+ header[0x28] = (BYTE)((vVersion >> 16) & 0xFF); // the "17" in OpenMPT 1.17
+ header[0x29] = 0x50 | (BYTE)((vVersion >> 24) & 0x0F); // the "1" in OpenMPT 1.17 + OpenMPT Identifier 5 (works only for versions up to 15.255 :))
header[0x2A] = 0x02; // Version = 1 => Signed samples
header[0x2B] = 0x00;
header[0x2C] = 'S';
@@ -558,11 +566,11 @@
ofs1 = ftell(f);
fwrite(insex, nbi, 0x50, f);
// Packing patterns
- ofs += nbi*0x50;
- for (i=0; i<nbp; i++)
+ ofs += nbi * 0x50;
+ for (i = 0; i < nbp; i++)
{
WORD len = 64;
- vector<BYTE> buffer(5*1024, 0);
+ vector<BYTE> buffer(5 * 1024, 0);
patptr[i] = ofs / 16;
if (Patterns[i])
{
@@ -581,16 +589,18 @@
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) note = 0xFF; // no note
+ else if (note >= NOTE_MIN_SPECIAL) note = 0xFE; // special notes (notecut, noteoff etc)
+ else if (note < 13) note = 0; // too low
+ 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;
+ vol = min(param, 64);
}
if (volcmd == VOLCMD_VOLUME) b |= 0x40; else
if (volcmd == VOLCMD_PANNING) { vol |= 0x80; b |= 0x40; }
@@ -629,9 +639,9 @@
}
}
}
- buffer[0] = (len - 2) & 0xFF;
- buffer[1] = (len - 2) >> 8;
- len = (len+15) & (~0x0F);
+ buffer[0] = (len) & 0xFF;
+ buffer[1] = (len) >> 8;
+ len = (len + 15) & (~0x0F);
fwrite(&buffer[0], len, 1, f);
ofs += len;
}
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-07-27 21:02:38 UTC (rev 307)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-07-28 13:34:18 UTC (rev 308)
@@ -1568,7 +1568,7 @@
}
if(GetModFlag(MSF_COMPATIBLE_PLAY) && (m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)))
{
- //IT compatibility 15. Retrigger
+ // IT compatibility 15. Retrigger
if (param)
pChn->nRetrigParam = (BYTE)(param & 0xFF);
@@ -1581,7 +1581,7 @@
}
else
{
- //MPT Retrig
+ // XM Retrig
if (param) pChn->nRetrigParam = (BYTE)(param & 0xFF); else param = pChn->nRetrigParam;
//rewbs.volOffset
//RetrigNote(nChn, param);
@@ -1875,7 +1875,7 @@
//end rewbs.fix
&& ((nPosJump != (int)m_nCurrentPattern) || (nBreakRow != (int)m_nRow)))
{
- if (nPosJump != (int)m_nCurrentPattern)
+ if (nPosJump != (int)m_nCurrentPattern && !((m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) && GetModFlag(MSF_COMPATIBLE_PLAY)))
{
for (UINT i=0; i<m_nChannels; i++) Chn[i].nPatternLoopCount = 0;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-07-31 13:09:34
|
Revision: 311
http://modplug.svn.sourceforge.net/modplug/?rev=311&view=rev
Author: saga-games
Date: 2009-07-31 12:56:26 +0000 (Fri, 31 Jul 2009)
Log Message:
-----------
[Fix] Retrig: A compatiblity change theoretically broke non-compatible Retrigger
[Imp] IT Compatibility: Improved IT compatible retrigger (didn't work if the retrigger didn't start together with a new note)
[Imp] IT Loader: Can now load IT files with very small patterns (< 4 rows)
[Imp] Mod Specifications: Decreased minimum pattern size for XM and IT format to 1 row. Experimental, but should not break anything (needs more testing).
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/mod_specifications.h
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2009-07-29 22:18:17 UTC (rev 310)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-07-31 12:56:26 UTC (rev 311)
@@ -928,7 +928,7 @@
bool interpretModplugmade = false;
bool hasModplugExtensions = false;
- if ((!lpStream) || (dwMemLength < 0x100)) return FALSE;
+ if ((!lpStream) || (dwMemLength < 0xC0)) return FALSE;
if ((pifh->id != 0x4D504D49 && pifh->id != 0x2e6D7074) || (pifh->insnum > 0xFF)
|| (!pifh->smpnum) || (pifh->smpnum >= MAX_SAMPLES) || (!pifh->ordnum)) return FALSE;
if (dwMemPos + pifh->ordnum + pifh->insnum*4
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-07-29 22:18:17 UTC (rev 310)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-07-31 12:56:26 UTC (rev 311)
@@ -746,7 +746,7 @@
pChn->nLeftVU = pChn->nRightVU = 0xFF;
pChn->dwFlags &= ~CHN_FILTER;
pChn->dwFlags |= CHN_FASTVOLRAMP;
- if(!GetModFlag(MSF_COMPATIBLE_PLAY) && (m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)))
+ if(!GetModFlag(MSF_COMPATIBLE_PLAY) || !(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)))
{
//IT compatibility 15. Retrigger will not be reset (Tremor doesn't store anything here, so we just don't reset this as well)
pChn->nRetrigCount = 0;
@@ -3018,7 +3018,7 @@
{
pChn->nRetrigCount = param & 0xf;
}
- else if (!--pChn->nRetrigCount)
+ else if (!pChn->nRetrigCount || !--pChn->nRetrigCount)
{
pChn->nRetrigCount = param & 0xf;
bDoRetrig = TRUE;
Modified: trunk/OpenMPT/soundlib/mod_specifications.h
===================================================================
--- trunk/OpenMPT/soundlib/mod_specifications.h 2009-07-29 22:18:17 UTC (rev 310)
+++ trunk/OpenMPT/soundlib/mod_specifications.h 2009-07-31 12:56:26 UTC (rev 311)
@@ -57,7 +57,7 @@
127, //Channel max
32, //Min tempo
512, //Max tempo
- 4, //Min pattern rows
+ 1, //Min pattern rows
1024, //Max pattern rows
25, //Max mod name length
4000, //SamplesMax
@@ -136,7 +136,7 @@
32, //Channel max
32, //Min tempo
255, //Max tempo
- 4, //Min pattern rows
+ 1, //Min pattern rows
256, //Max pattern rows
20, //Max mod name length
31, //SamplesMax
@@ -162,7 +162,7 @@
127, //Channel max
32, //Min tempo
512, //Max tempo
- 4, //Min pattern rows
+ 1, //Min pattern rows
1024, //Max pattern rows
20, //Max mod name length
4000, //SamplesMax
@@ -238,7 +238,7 @@
64, //Channel max
32, //Min tempo
255, //Max tempo
- 4, //Min pattern rows
+ 1, //Min pattern rows
256, //Max pattern rows
25, //Max mod name length
256, //SamplesMax
@@ -263,7 +263,7 @@
127, //Channel max
32, //Min tempo
512, //Max tempo
- 4, //Min pattern rows
+ 1, //Min pattern rows
1024, //Max pattern rows
25, //Max mod name length
4000, //SamplesMax
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-08-14 09:57:44
|
Revision: 322
http://modplug.svn.sourceforge.net/modplug/?rev=322&view=rev
Author: saga-games
Date: 2009-08-14 09:57:35 +0000 (Fri, 14 Aug 2009)
Log Message:
-----------
[Fix] XM Loading: Don't ignore last pattern if XM has no instruments
[Fix] IT Loading: Don't set "made with modplug" flag for IT files that were made with compatibility export
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/Load_xm.cpp
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2009-08-13 22:23:15 UTC (rev 321)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-08-14 09:57:35 UTC (rev 322)
@@ -984,10 +984,10 @@
}
}
- if((pifh->cwtv & 0xF000) == 0x5000) // OpenMPT Version number (Major.Minor)
+ if((pifh->cwtv & 0xF000) == 0x5000) // OpenMPT Version number (Major.Minor) - we won't interpret this as "made with modplug" as this is used by compatibility export
{
m_dwLastSavedWithVersion = (pifh->cwtv & 0x0FFF) << 16;
- interpretModplugmade = true;
+ //interpretModplugmade = true;
}
if (pifh->flags & 0x08) m_dwSongFlags |= SONG_LINEARSLIDES;
Modified: trunk/OpenMPT/soundlib/Load_xm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-08-13 22:23:15 UTC (rev 321)
+++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-08-14 09:57:35 UTC (rev 322)
@@ -188,7 +188,7 @@
packsize = LittleEndianW(*((WORD *)(lpStream+dwMemPos+7)));
if (dwMemPos + dwSize + 4 > dwMemLength) return true;
dwMemPos += dwSize;
- if (dwMemPos + packsize + 4 > dwMemLength) return true;
+ if (dwMemPos + packsize > dwMemLength) return true;
MODCOMMAND *p;
if (ipatmap < MAX_PATTERNS)
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-08-22 10:21:34
|
Revision: 337
http://modplug.svn.sourceforge.net/modplug/?rev=337&view=rev
Author: saga-games
Date: 2009-08-22 10:21:22 +0000 (Sat, 22 Aug 2009)
Log Message:
-----------
[Fix] A brand new PSM loader! Ditched the old and buggy loader as the new loader works way better, it can even handle modules from Extreme Pinball. Some finetuning is still mandatory, though.
[Fix] S3M Loading: Disable loop for files with very short loop at the beginning of the sample
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_psm.cpp
trunk/OpenMPT/soundlib/Load_s3m.cpp
Modified: trunk/OpenMPT/soundlib/Load_psm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_psm.cpp 2009-08-20 20:43:52 UTC (rev 336)
+++ trunk/OpenMPT/soundlib/Load_psm.cpp 2009-08-22 10:21:22 UTC (rev 337)
@@ -1,841 +1,558 @@
/*
- * This source code is public domain.
+ * Purpose: Load new PSM (ProTracker Studio) modules
+ * Authors: Johannes Schultz
*
- * Authors: Olivier Lapicque <oli...@jp...>
-*/
+ * This is partly based on http://www.shikadi.net/moddingwiki/ProTracker_Studio_Module
+ * and partly reverse-engineered.
+ *
+ * What's playing?
+ * - Epic Pinball - Seems to be working perfectly, apart from some portas? (esp. Deep Sea, Shareware Info - Linear freq slides needed!?)
+ * - Extreme Pinball - Default tempo / speed / restart position of subtunes is missing.
+ * I'm using the last default values, restart position is still completely missing
+ * - Jazz Jackrabbit - Hmm, I don't like some of the portas, but apart from that it's great. (same problem as Epic Pinball)
+ * - One Must Fall! - Perfect! (I modelled the volume slide and portamento conversion after this, as I got the original MTM files)
+ * - Silverball - Currently not supported (old PSM16 format)
+ */
-
-///////////////////////////////////////////////////
-//
-// PSM module loader
-//
-///////////////////////////////////////////////////
#include "stdafx.h"
#include "sndfile.h"
-//#define PSM_LOG
-
-#define PSM_ID_NEW 0x204d5350 // "PSM "
-#define PSM_ID_OLD 0xfe4d5350 // "PSM\xFE"
-#define IFFID_FILE 0x454c4946
-#define IFFID_TITL 0x4c544954
-#define IFFID_SDFT 0x54464453
-#define IFFID_PBOD 0x444f4250
-#define IFFID_SONG 0x474e4f53
-#define IFFID_PATT 0x54544150
-#define IFFID_DSMP 0x504d5344
-#define IFFID_OPLH 0x484c504f
-
#pragma pack(1)
-typedef struct _PSMCHUNK
+struct PSMHEADER
{
- DWORD id;
- DWORD len;
- DWORD listid;
-} PSMCHUNK;
+ DWORD formatID; // "PSM " (new format)
+ DWORD fileSize; // Filesize - 12
+ DWORD fileInfoID; // "FILE" Start of file info
+};
-typedef struct _PSMSONGHDR
+struct PSMSONGHEADER
{
- CHAR songname[8]; // "MAINSONG"
- BYTE reserved1;
- BYTE reserved2;
- BYTE channels;
-} PSMSONGHDR;
+ CHAR songType[9]; // Mostly "MAINSONG " (But not in Extreme Pinball!)
+ BYTE compression; // 1 - uncompressed
+ BYTE numChannels; // Number of channels, usually 4
-typedef struct _PSMPATTERN
+};
+
+struct PSMSAMPLEHEADERTEST // apparently, this is wrong.
{
- DWORD size;
- DWORD name;
- WORD rows;
- WORD reserved1;
- BYTE data[4];
-} PSMPATTERN;
+ CHAR sampleFormat[9];
+ DWORD sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal)
+ CHAR sampleName[33];
+ CHAR unknown1[6]; // 00 00 00 00 00 FF
+ WORD sampleNumber;
+ DWORD loopStart;
+ CHAR loop; // 1 = loop
+ CHAR unknown2[3]; // 00 00 00 00 00 FF
+ DWORD loopEnd; // FF FF FF FF = end of sample
+ WORD unknown3;
+ CHAR defaultVolume;
+ DWORD unknown4;
+ WORD C5Freq;
+ CHAR padding[21]; // 00 ... 00
+};
-typedef struct _PSMSAMPLE
+struct PSMSAMPLEHEADER // Use this instead
{
BYTE flags;
- CHAR songname[8];
- DWORD smpid;
- CHAR samplename[34];
- DWORD reserved1;
- BYTE reserved2;
- BYTE insno;
- BYTE reserved3;
- DWORD length;
- DWORD loopstart;
- DWORD loopend;
- WORD reserved4;
- BYTE defvol;
- DWORD reserved5;
- DWORD samplerate;
- BYTE reserved6[19];
-} PSMSAMPLE;
+ CHAR sampleFormat[8];
+ DWORD sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal)
+ CHAR sampleName[33];
+ CHAR unknown1[6]; // 00 00 00 00 00 FF
+ WORD sampleNumber;
+ DWORD sampleLength;
+ DWORD loopStart;
+ DWORD loopEnd; // FF FF FF FF = end of sample
+ WORD unknown3;
+ CHAR defaultVolume;
+ DWORD unknown4;
+ WORD C5Freq;
+ CHAR unknown5[21]; // 00 ... 00
+};
#pragma pack()
+BYTE convert_psm_param(BYTE param)
+{
+ // special conversion of some PSM parameters. is this done correctly?
+ return param >> 1;
+ //return (param + 1) >> 1;
+}
-bool CSoundFile::ReadPSM(LPCBYTE lpStream, DWORD dwMemLength)
-//-----------------------------------------------------------
+bool CSoundFile::ReadPSM(const LPCBYTE lpStream, const DWORD dwMemLength)
+//-----------------------------------------------------------------------
{
- PSMCHUNK *pfh = (PSMCHUNK *)lpStream;
- DWORD dwMemPos, dwSongPos;
- DWORD smpnames[MAX_SAMPLES];
- DWORD patptrs[MAX_PATTERNS];
- BYTE samplemap[MAX_SAMPLES];
- UINT nPatterns;
+ #define ASSERT_CAN_READ(x) \
+ if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false;
- // Chunk0: "PSM ",filesize,"FILE"
- if (dwMemLength < 256) return false;
- if (pfh->id == PSM_ID_OLD)
- {
- #ifdef PSM_LOG
- Log("Old PSM format not supported\n");
- #endif
- return false;
- }
- if ((pfh->id != PSM_ID_NEW) || (pfh->len+12 > dwMemLength) || (pfh->listid != IFFID_FILE)) return false;
+ DWORD dwMemPos = 0;
+
+ ASSERT_CAN_READ(12);
+ PSMHEADER shdr;
+ memcpy(&shdr, lpStream, sizeof(PSMHEADER));
+ if(LittleEndian(shdr.formatID) != 0x204d5350 // "PSM "
+ || LittleEndian(shdr.fileSize) != dwMemLength - 12
+ || LittleEndian(shdr.fileInfoID) != 0x454C4946 // "FILE"
+ ) return false;
+
+ // Yep, this seems to be a valid file.
m_nType = MOD_TYPE_PSM;
- m_nChannels = 16;
- m_nSamples = 0;
- nPatterns = 0;
- dwMemPos = 12;
- dwSongPos = 0;
- for (UINT iChPan=0; iChPan<16; iChPan++)
+ //m_dwSongFlags |= SONG_LINEARSLIDES; // TODO
+ m_nChannels = 0;
+
+ dwMemPos += 12;
+
+ memset(m_szNames, 0, sizeof(m_szNames));
+
+ m_nVSTiVolume = m_nSamplePreAmp = 48; // not supported in this format, so use a good default value
+
+ // pattern offset and identifier
+ PATTERNINDEX numPatterns = 0;
+ vector<DWORD> patternOffsets;
+ vector<DWORD> patternIDs;
+ patternOffsets.clear();
+ patternIDs.clear();
+ Order.clear();
+
+ std::string sComment; // we will store some information about the tune here
+
+ while(dwMemPos + 8 < dwMemLength)
{
- UINT pan = (((iChPan & 3) == 1) || ((iChPan&3)==2)) ? 0xC0 : 0x40;
- ChnSettings[iChPan].nPan = pan;
- }
- while (dwMemPos+8 < dwMemLength)
- {
- PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
- if ((pchunk->len >= dwMemLength - 8) || (dwMemPos + pchunk->len + 8 > dwMemLength)) break;
+ // Skip through the chunks
+ ASSERT_CAN_READ(8);
+ DWORD chunkID = LittleEndian(*(DWORD *)(lpStream + dwMemPos));
+ DWORD chunkSize = LittleEndian(*(DWORD *)(lpStream + dwMemPos + 4));
dwMemPos += 8;
- PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
- ULONG len = pchunk->len;
- if (len) switch(pchunk->id)
+
+ ASSERT_CAN_READ(chunkSize);
+
+ switch(chunkID)
{
- // "TITL": Song title
- case IFFID_TITL:
- if (!pdata[0]) { pdata++; len--; }
- memcpy(m_szNames[0], pdata, (len>31) ? 31 : len);
+ case 0x4C544954: // "TITL" - Song Title
+ memcpy(m_szNames[0], lpStream + dwMemPos, (chunkSize < 31) ? chunkSize : 31);
m_szNames[0][31] = 0;
break;
- // "PBOD": Pattern
- case IFFID_PBOD:
- if ((len >= 12) && (nPatterns < MAX_PATTERNS))
- {
- patptrs[nPatterns++] = dwMemPos-8;
- }
+
+ case 0x54464453: // "SDFT" - Format info (song data starts here)
+ if(chunkSize != 8 || memcmp(lpStream + dwMemPos, "MAINSONG", 8)) return false;
break;
- // "SONG": Song description
- case IFFID_SONG:
- if ((len >= sizeof(PSMSONGHDR)+8) && (!dwSongPos))
- {
- dwSongPos = dwMemPos - 8;
- }
+
+ case 0x444F4250: // "PBOD" - Pattern data of a single pattern
+ if(chunkSize < 4 || chunkSize != LittleEndian(*(DWORD *)(lpStream + dwMemPos))) return false; // same value twice
+
+ // Pattern ID (something like "P0 " or "P13 ") follows
+ if(memcmp(lpStream + dwMemPos + 4, "P", 1)) return false;
+ patternOffsets.push_back(dwMemPos + 8);
+ patternIDs.push_back(*(DWORD *)(lpStream + dwMemPos + 4));
+ numPatterns++;
+
+ // Convert later as we have to know how many channels there are.
break;
- // "DSMP": Sample Data
- case IFFID_DSMP:
- if ((len >= sizeof(PSMSAMPLE)) && (m_nSamples+1 < MAX_SAMPLES))
+
+ case 0x474E4F53: // "SONG" - Information about this file (channel count etc)
+ // We will not check for the "song type", because it is not ALWAYS "MAINSONG " (Extreme Pinball seems to use other song types for the sub songs)
+ // However, the last char always seems to be a space char.
{
- m_nSamples++;
- MODSAMPLE *pSmp = &Samples[m_nSamples];
- PSMSAMPLE *psmp = (PSMSAMPLE *)pdata;
- 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
- pSmp->nGlobalVol = 0x40;
- pSmp->nC5Speed = psmp->samplerate;
- pSmp->nLength = psmp->length;
- pSmp->nLoopStart = psmp->loopstart;
- pSmp->nLoopEnd = psmp->loopend;
- pSmp->nPan = 128;
- pSmp->nVolume = (psmp->defvol+1) * 2;
- pSmp->uFlags = (psmp->flags & 0x80) ? CHN_LOOP : 0;
- if (pSmp->nLoopStart > 0) pSmp->nLoopStart--;
- // Point to sample data
- pdata += 0x60;
- len -= 0x60;
- // Load sample data
- if ((pSmp->nLength > 3) && (len > 3))
+ if(chunkSize < sizeof(PSMSONGHEADER)) return false;
+ PSMSONGHEADER *pSong = (PSMSONGHEADER *)(lpStream + dwMemPos);
+ if(pSong->compression != 0x01) return false;
+ m_nChannels = max(m_nChannels, pSong->numChannels); // subsongs *might* have different channel count
+
+ CHAR cSongName[10];
+ memcpy(cSongName, &pSong->songType, 9);
+ cSongName[9] = 0;
+ sComment += "\r\nSubsong: ";
+ sComment += cSongName;
+
+ DWORD dwChunkPos = dwMemPos + sizeof(PSMSONGHEADER);
+
+ // Sub chunks
+ while(dwChunkPos + 8 < dwMemPos + chunkSize)
{
- ReadSample(pSmp, RS_PCM8D, (LPCSTR)pdata, len);
- } else
- {
- pSmp->nLength = 0;
- }
- }
- break;
- #if 0
- default:
- {
- CHAR s[8], s2[64];
- *(DWORD *)s = pchunk->id;
- s[4] = 0;
- wsprintf(s2, "%s: %4d bytes @ %4d\n", s, pchunk->len, dwMemPos);
- OutputDebugString(s2);
- }
- #endif
- }
- dwMemPos += pchunk->len;
- }
- // Step #1: convert song structure
- PSMSONGHDR *pSong = (PSMSONGHDR *)(lpStream+dwSongPos+8);
- if ((!dwSongPos) || (pSong->channels < 2) || (pSong->channels > 32)) return true;
- m_nChannels = pSong->channels;
- // Valid song header -> convert attached chunks
- {
- DWORD dwSongEnd = dwSongPos + 8 + *(DWORD *)(lpStream+dwSongPos+4);
- dwMemPos = dwSongPos + 8 + 11; // sizeof(PSMCHUNK)+sizeof(PSMSONGHDR)
- while (dwMemPos + 8 < dwSongEnd)
- {
- PSMCHUNK *pchunk = (PSMCHUNK *)(lpStream+dwMemPos);
- dwMemPos += 8;
- if ((pchunk->len > dwSongEnd) || (dwMemPos + pchunk->len > dwSongEnd)) break;
- PUCHAR pdata = (PUCHAR)(lpStream+dwMemPos);
- ULONG len = pchunk->len;
- switch(pchunk->id)
- {
- case IFFID_OPLH:
- if (len >= 0x20)
- {
- UINT pos = len - 3;
- while (pos > 5)
+ DWORD subChunkID = LittleEndian(*(DWORD *)(lpStream + dwChunkPos));
+ DWORD subChunkSize = LittleEndian(*(DWORD *)(lpStream + dwChunkPos + 4));
+ dwChunkPos += 8;
+
+ switch(subChunkID)
{
- BOOL bFound = FALSE;
- pos -= 5;
- DWORD dwName = *(DWORD *)(pdata+pos);
- for (UINT i=0; i<nPatterns; i++)
+ case 0x45544144: // "DATE" - Song date (YYMMDD)
+ if(subChunkSize < 6) break;
+ CHAR cDate[7];
+ memcpy(cDate, lpStream + dwChunkPos, 6);
+ cDate[6] = 0;
+ sComment += "\r\nDate: ";
+ sComment += cDate;
+ // We don't care about the date.
+ break;
+
+ case 0x484C504F: // "OPLH" - Order list, channel + module settings
{
- DWORD dwPatName = ((PSMPATTERN *)(lpStream+patptrs[i]+8))->name;
- if (dwName == dwPatName)
+ if(subChunkSize < 9) return false;
+ // First byte = "Memory alloc, roughly ordlen + 10, if too small, song freezes"
+ if(LittleEndian(*(DWORD *)(lpStream + dwChunkPos + 1)) != 0xFF000C00 // "Something"
+ || LittleEndian(*(DWORD *)(lpStream + dwChunkPos + 5)) != 0x00010000) // "Something"
+ return false;
+
+ // Now, the interesting part begins!
+ DWORD dwSettingsOffset = dwChunkPos + 9;
+ while(dwSettingsOffset - dwChunkPos + 1 < subChunkSize)
{
- bFound = TRUE;
- break;
+ switch(lpStream[dwSettingsOffset])
+ {
+ case 0x01: // Order list item
+ if(dwSettingsOffset - dwChunkPos + 5 > subChunkSize) return false;
+ // Pattern name follows - find pattern (this is the orderlist)
+ for(PATTERNINDEX i = 0; i < patternIDs.size(); i++)
+ {
+ if(patternIDs[i] == *(DWORD *)(lpStream + dwSettingsOffset + 1))
+ {
+ Order.push_back(i);
+ break;
+ }
+ }
+ dwSettingsOffset += 5;
+ break;
+
+ case 0x04: // "end?" "04 03 00 00" in most cases (not Extreme Pinball - maybe restart positions are dumped here?)
+ if(dwSettingsOffset - dwChunkPos + 4 > subChunkSize) return false;
+ dwSettingsOffset += 4;
+ break;
+
+ case 0x07: // Default Speed
+ if(dwSettingsOffset - dwChunkPos + 2 > subChunkSize) break;
+ // NOTE: This should not be global! (Extreme Pinball!!!)
+ m_nDefaultSpeed = lpStream[dwSettingsOffset + 1];
+ dwSettingsOffset += 2;
+ break;
+
+ case 0x08: // Default Tempo
+ if(dwSettingsOffset - dwChunkPos + 2 > subChunkSize) break;
+ // Same note as above!
+ m_nDefaultTempo = lpStream[dwSettingsOffset + 1];
+ dwSettingsOffset += 2;
+ break;
+
+ case 0x0D: // This is a channel header
+ if(dwSettingsOffset - dwChunkPos + 4 > subChunkSize) break;
+ ChnSettings[min(lpStream[dwSettingsOffset + 1], pSong->numChannels)].nPan = lpStream[dwSettingsOffset + 2];
+ // Last byte: "either 0, 2 or 4 (Some sort of priority?)"
+ dwSettingsOffset += 4;
+ break;
+
+ case 0x0E: // Unknown - "0E <ChnID> FF"
+ if(dwSettingsOffset - dwChunkPos + 3 > subChunkSize) break;
+ dwSettingsOffset += 3;
+ break;
+
+ case 0x00: // "end?"
+ dwSettingsOffset += 1;
+ break;
+
+ default: // How the hell should this happen? I've listened through all existing PSM files. :)
+ CString s;
+ s.Format("Please report to the OpenMPT team: Unknown chunk %d found at position %d (in the OPLH chunk of this PSM file)", lpStream[dwSettingsOffset], dwSettingsOffset);
+ MessageBox(NULL, s, TEXT("OpenMPT PSM import"), MB_ICONERROR);
+ return false;
+ break;
+
+ }
}
+ Order.push_back(Order.GetInvalidPatIndex());
}
- if ((!bFound) && (pdata[pos+1] > 0) && (pdata[pos+1] <= 0x10)
- && (pdata[pos+3] > 0x40) && (pdata[pos+3] < 0xC0))
- {
- m_nDefaultSpeed = pdata[pos+1];
- m_nDefaultTempo = pdata[pos+3];
- break;
- }
+ break;
+
+ case 0x54544150: // PATT - Pattern list
+ // We don't really need this.
+ break;
+
+ case 0x4D415344: // DSAM - Sample list
+ // We don't need this either.
+ break;
+
+ default:
+ break;
+
}
- UINT iOrd = 0;
- Order.resize(MAX_ORDERS, Order.GetInvalidPatIndex());
- while ((pos+5<len) && (iOrd < MAX_ORDERS))
- {
- DWORD dwName = *(DWORD *)(pdata+pos);
- for (UINT i=0; i<nPatterns; i++)
- {
- DWORD dwPatName = ((PSMPATTERN *)(lpStream+patptrs[i]+8))->name;
- if (dwName == dwPatName)
- {
- Order[iOrd++] = i;
- break;
- }
- }
- pos += 5;
- }
+
+ dwChunkPos += subChunkSize;
}
- break;
}
- dwMemPos += pchunk->len;
+
+ break;
+
+ case 0x504D5344: // DSMP - Samples
+
+ {
+ if(chunkSize < sizeof(PSMSAMPLEHEADER)) return false;
+ PSMSAMPLEHEADER *pSample = (PSMSAMPLEHEADER *)(lpStream + dwMemPos);
+ SAMPLEINDEX smp = (SAMPLEINDEX)(LittleEndianW(pSample->sampleNumber) + 1);
+ m_nSamples = max(m_nSamples, smp);
+ memcpy(m_szNames[smp], pSample->sampleName, 31);
+ m_szNames[0][31] = 0;
+
+ Samples[smp].nGlobalVol = 0x40;
+ Samples[smp].nC5Speed = LittleEndianW(pSample->C5Freq);
+ Samples[smp].nLength = LittleEndian(pSample->sampleLength);
+ Samples[smp].nLoopStart = LittleEndian(pSample->loopStart);
+ Samples[smp].nLoopEnd = LittleEndian(pSample->loopEnd);
+ Samples[smp].nPan = 128;
+ Samples[smp].nVolume = (pSample->defaultVolume + 1) << 1;
+ Samples[smp].uFlags = (pSample->flags & 0x80) ? CHN_LOOP : 0;
+ if(Samples[smp].nLoopStart > 0) Samples[smp].nLoopStart--;
+ if(Samples[smp].nLoopEnd == 0xFFFFFF) Samples[smp].nLoopEnd = Samples[smp].nLength;
+
+ // Delta-encoded samples
+ ReadSample(&Samples[smp], RS_PCM8D, (LPCSTR)(lpStream + dwMemPos + sizeof(PSMSAMPLEHEADER)), Samples[smp].nLength);
+ }
+
+ break;
+
+ default:
+ break;
+
}
+
+ dwMemPos += chunkSize;
}
- // Step #2: convert patterns
- for (UINT nPat=0; nPat<nPatterns; nPat++)
+ if(m_nChannels == 0)
+ return false;
+
+ // Now that we know the number of channels, we can go through all the patterns.
+ for(PATTERNINDEX i = 0; i < numPatterns; i++)
{
- PSMPATTERN *pPsmPat = (PSMPATTERN *)(lpStream+patptrs[nPat]+8);
- 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;
- if(Patterns.Insert(nPat, nRows))
+ DWORD dwPatternOffset = patternOffsets[i];
+ if(dwPatternOffset + 2 > dwMemLength) return false;
+ WORD patternSize = LittleEndianW(*(WORD *)(lpStream + dwPatternOffset));
+ dwPatternOffset += 2;
+
+ if(Patterns.Insert(i, patternSize))
+ {
+ CString s;
+ s.Format(TEXT("Allocating patterns failed starting from pattern %u"), i);
+ MessageBox(NULL, s, TEXT("OpenMPT PSM import"), MB_ICONERROR);
break;
+ }
- MODCOMMAND *m = Patterns[nPat];
- BYTE *p = pPsmPat->data;
- UINT pos = 0;
- UINT row = 0;
- UINT oldch = 0;
- BOOL bNewRow = FALSE;
- #ifdef PSM_LOG
- Log("Pattern %d at offset 0x%04X\n", nPat, (DWORD)(p - (BYTE *)lpStream));
- #endif
- while ((row < nRows) && (pos+1 < len))
+ // Read pattern.
+ MODCOMMAND *row_data;
+ row_data = Patterns[i];
+
+ for(int nRow = 0; nRow < patternSize; nRow++)
{
- UINT flags = p[pos++];
- UINT ch = p[pos++];
+ if(dwPatternOffset + 2 > dwMemLength) return false;
+ WORD rowSize = LittleEndianW(*(WORD *)(lpStream + dwPatternOffset));
- #ifdef PSM_LOG
- //Log("flags+ch: %02X.%02X\n", flags, ch);
- #endif
- if (((flags & 0xf0) == 0x10) && (ch <= oldch) /*&& (!bNewRow)*/)
+ DWORD dwRowOffset = dwPatternOffset + 2;
+
+ while(dwRowOffset < dwPatternOffset + rowSize)
{
- if ((pos+1<len) && (!(p[pos] & 0x0f)) && (p[pos+1] < m_nChannels))
+ if(dwRowOffset + 1 > dwMemLength) return false;
+ BYTE mask = lpStream[dwRowOffset];
+ // Point to the correct channel
+ MODCOMMAND *m = row_data + min(m_nChannels, lpStream[dwRowOffset + 1]);
+ dwRowOffset += 2;
+
+ if(mask & 0x80)
{
- #ifdef PSM_LOG
- //if (!nPat) Log("Continuing on new row\n");
- #endif
- row++;
- m += m_nChannels;
- oldch = ch;
- continue;
+ if(dwRowOffset + 1 > dwMemLength) return false;
+ // Note present
+ BYTE bNote = lpStream[dwRowOffset];
+ bNote = (bNote & 0x0F) + 12 * (bNote >> 4) + 13;
+ m->note = bNote;
+ dwRowOffset++;
}
- }
- if ((pos >= len) || (row >= nRows)) break;
- if (!(flags & 0xf0))
- {
- #ifdef PSM_LOG
- //if (!nPat) Log("EOR(%d): %02X.%02X\n", row, p[pos], p[pos+1]);
- #endif
- 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 & 0x40) && (pos+1 < len))
- {
- UINT note = p[pos++];
- UINT nins = p[pos++];
- #ifdef PSM_LOG
- //if (!nPat) Log("note+ins: %02X.%02X\n", note, nins);
- if ((!nPat) && (nins >= m_nSamples)) Log("WARNING: invalid instrument number (%d)\n", nins);
- #endif
- 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))
- {
- m[ch].volcmd = VOLCMD_VOLUME;
- m[ch].vol = p[pos++] / 2;
- }
- // Effect
- if ((flags & 0x10) && (pos+1 < len))
- {
- UINT command = p[pos++];
- UINT param = p[pos++];
- // Convert effects
- switch(command)
+
+ if(mask & 0x40)
{
- // 01: fine volslide up
- 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;
- // 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; break;
- // 3E: tempo
- case 0x3E: command = CMD_TEMPO; break;
- // Unknown
- default:
- #ifdef PSM_LOG
- Log("Unknown PSM effect pat=%d row=%d ch=%d: %02X.%02X\n", nPat, row, ch, command, param);
- #endif
- command = param = 0;
+ if(dwRowOffset + 1 > dwMemLength) return false;
+ // Instrument present
+ m->instr = lpStream[dwRowOffset] + 1;
+ dwRowOffset++;
}
- m[ch].command = (BYTE)command;
- m[ch].param = (BYTE)param;
- }
- oldch = ch;
- }
- #ifdef PSM_LOG
- if (pos < len)
- {
- Log("Pattern %d: %d/%d[%d] rows (%d bytes) -> %d bytes left\n", nPat, row, nRows, pPsmPat->rows, pPsmPat->size, len-pos);
- }
- #endif
- }
- // Done (finally!)
- return true;
-}
+ if(mask & 0x20)
+ {
+ if(dwRowOffset + 1 > dwMemLength) return false;
+ // Volume present
+ m->volcmd = VOLCMD_VOLUME;
+ m->vol = (min(lpStream[dwRowOffset], 127)) >> 1;
+ dwRowOffset++;
+ }
+ if(mask & 0x10)
+ {
+ // Effect present - convert
+ if(dwRowOffset + 2 > dwMemLength) return false;
+ BYTE command = lpStream[dwRowOffset], param = lpStream[dwRowOffset + 1];
-//////////////////////////////////////////////////////////////
-//
-// PSM Old Format
-//
+ switch(command)
+ {
+ // Volslides
+ case 0x01: // fine volslide up
+ command = CMD_VOLUMESLIDE;
+ param = (param << 3) | 0x0F;
+ break;
+ case 0x02: // volslide up
+ command = CMD_VOLUMESLIDE;
+ param = (param << 3);
+ break;
+ case 0x03: // fine volslide down
+ command = CMD_VOLUMESLIDE;
+ param = 0xF0 | (param >> 1);
+ break;
+ case 0x04: // volslide down
+ command = CMD_VOLUMESLIDE;
+ param >>= 1;
+ break;
-/*
+ // Portamento
+ case 0x0B: // fine portamento up
+ command = CMD_PORTAMENTOUP;
+ param = 0xF0 | convert_psm_param(param);
+ break;
+ case 0x0C: // portamento up
+ command = CMD_PORTAMENTOUP;
+ param = convert_psm_param(param);
+ break;
+ case 0x0D: // fine portamento down
+ command = CMD_PORTAMENTODOWN;
+ param = 0xF0 | convert_psm_param(param);
+ break;
+ case 0x0E: // portamento down
+ command = CMD_PORTAMENTODOWN;
+ param = convert_psm_param(param);
+ break;
+ case 0x0F: // tone portamento
+ command = CMD_TONEPORTAMENTO;
+ param = convert_psm_param(param);
+ break;
+ case 0x10: // glissando control
+ command = CMD_S3MCMDEX;
+ param = 0x10 | (param & 0x01);
+ break;
+ case 0x11: // tone portamento + volslide up
+ command = CMD_TONEPORTAVOL;
+ param = param & 0xF0;
+ break;
+ case 0x12: // tone portamento + volslide down
+ command = CMD_TONEPORTAVOL;
+ param = (param >> 4) & 0x0F;
+ break;
-CONST
- c_PSM_MaxOrder = $FF;
- c_PSM_MaxSample = $FF;
- c_PSM_MaxChannel = $0F;
+ // Vibrato
+ case 0x15: // vibrato
+ command = CMD_VIBRATO;
+ break;
+ case 0x16: // vibrato waveform
+ command = CMD_S3MCMDEX;
+ param = 0x30 | (param & 0x0F);
+ break;
+ case 0x17: // vibrato + volslide up
+ command = CMD_VIBRATOVOL;
+ param = 0xF0 | param;
+ break;
+ case 0x18: // vibrato + volslide down
+ command = CMD_VIBRATOVOL;
+ break;
- TYPE
- PPSM_Header = ^TPSM_Header;
- TPSM_Header = RECORD
- PSM_Sign : ARRAY[01..04] OF CHAR; { PSM + #254 }
- PSM_SongName : ARRAY[01..58] OF CHAR;
- PSM_Byte00 : BYTE;
- PSM_Byte1A : BYTE;
- PSM_Unknown00 : BYTE;
- PSM_Unknown01 : BYTE;
- PSM_Unknown02 : BYTE;
- PSM_Speed : BYTE;
- PSM_Tempo : BYTE;
- PSM_Unknown03 : BYTE;
- PSM_Unknown04 : WORD;
- PSM_OrderLength : WORD;
- PSM_PatternNumber : WORD;
- PSM_SampleNumber : WORD;
- PSM_ChannelNumber : WORD;
- PSM_ChannelUsed : WORD;
- PSM_OrderPosition : LONGINT;
- PSM_ChannelSettingPosition : LONGINT;
- PSM_PatternPosition : LONGINT;
- PSM_SamplePosition : LONGINT;
- { *** perhaps there are some more infos in a larger header,
- but i have not decoded it and so it apears here NOT }
- END;
+ // Tremolo
+ case 0x1F: // tremolo
+ command = CMD_TREMOLO;
+ break;
+ case 0x20: // tremolo waveform
+ command = CMD_S3MCMDEX;
+ param = 0x40 | (param & 0x0F);
+ break;
- PPSM_Sample = ^TPSM_Sample;
- TPSM_Sample = RECORD
- PSM_SampleFileName : ARRAY[01..12] OF CHAR;
- PSM_SampleByte00 : BYTE;
- PSM_SampleName : ARRAY[01..22] OF CHAR;
- PSM_SampleUnknown00 : ARRAY[01..02] OF BYTE;
- PSM_SamplePosition : LONGINT;
- PSM_SampleUnknown01 : ARRAY[01..04] OF BYTE;
- PSM_SampleNumber : BYTE;
- PSM_SampleFlags : WORD;
- PSM_SampleLength : LONGINT;
- PSM_SampleLoopBegin : LONGINT;
- PSM_SampleLoopEnd : LONGINT;
- PSM_Unknown03 : BYTE;
- PSM_SampleVolume : BYTE;
- PSM_SampleC5Speed : WORD;
- END;
+ // Sample commands
+ case 0x29: // 3-byte offset - we only support the middle byte.
+ if(dwRowOffset + 4 > dwMemLength) return false;
+ command = CMD_OFFSET;
+ param = lpStream[dwRowOffset + 2];
+ dwRowOffset += 2;
+ break;
+ case 0x2A: // set finetune
+ command = CMD_S3MCMDEX;
+ param = 0x40 | (param & 0x0F);
+ break;
+ case 0x2B: // note cut
+ command = CMD_S3MCMDEX;
+ param = 0xC0 | (param & 0x0F);
+ break;
+ case 0x2C: // note delay
+ command = CMD_S3MCMDEX;
+ param = 0xD0 | (param & 0x0F);
+ break;
- PPSM_SampleList = ^TPSM_SampleList;
- TPSM_SampleList = ARRAY[01..c_PSM_MaxSample] OF TPSM_Sample;
+ // Position change
+ case 0x33: // position jump
+ command = CMD_POSITIONJUMP;
+ break;
+ case 0x34: // pattern break
+ command = CMD_PATTERNBREAK;
+ break;
+ case 0x35: // loop pattern
+ command = CMD_S3MCMDEX;
+ param = 0xB0 | (param & 0x0F);
+ break;
+ case 0x36: // pattern delay
+ command = CMD_S3MCMDEX;
+ param = 0xE0 | (param & 0x0F);
+ break;
- PPSM_Order = ^TPSM_Order;
- TPSM_Order = ARRAY[00..c_PSM_MaxOrder] OF BYTE;
+ // speed change
+ case 0x3D: // set speed
+ command = CMD_SPEED;
+ break;
+ case 0x3E: // set tempo
+ command = CMD_TEMPO;
+ break;
- PPSM_ChannelSettings = ^TPSM_ChannelSettings;
- TPSM_ChannelSettings = ARRAY[00..c_PSM_MaxChannel] OF BYTE;
+ // misc commands
+ case 0x47: // arpeggio
+ command = CMD_ARPEGGIO;
+ break;
+ case 0x48: // set finetune
+ command = CMD_MODCMDEX;
+ param = 0x50 | (param & 0x0F);
+ break;
+ case 0x49: // set balance
+ command = CMD_S3MCMDEX;
+ param = 0x80 | (param & 0x0F);
+ break;
- CONST
- PSM_NotesInPattern : BYTE = $00;
- PSM_ChannelInPattern : BYTE = $00;
+ default:
+ //ASSERT(false);
+ break;
- CONST
- c_PSM_SetSpeed = 60;
+ }
- FUNCTION PSM_Size(FileName : STRING;FilePosition : LONGINT) : LONGINT;
- BEGIN
- END;
+ m->command = command;
+ m->param = param;
- PROCEDURE PSM_UnpackPattern(VAR Source,Destination;PatternLength : WORD);
- VAR
- Witz : ARRAY[00..04] OF WORD;
- I1,I2 : WORD;
- I3,I4 : WORD;
- TopicalByte : ^BYTE;
- Pattern : PUnpackedPattern;
- ChannelP : BYTE;
- NoteP : BYTE;
- InfoByte : BYTE;
- CodeByte : BYTE;
- InfoWord : WORD;
- Effect : BYTE;
- Opperand : BYTE;
- Panning : BYTE;
- Volume : BYTE;
- PrevInfo : BYTE;
- InfoIndex : BYTE;
- BEGIN
- Pattern := @Destination;
- TopicalByte := @Source;
- { *** Initialize patttern }
- F...
[truncated message content] |
|
From: <sag...@us...> - 2009-08-23 22:13:59
|
Revision: 339
http://modplug.svn.sourceforge.net/modplug/?rev=339&view=rev
Author: saga-games
Date: 2009-08-23 21:07:17 +0000 (Sun, 23 Aug 2009)
Log Message:
-----------
[Fix] PSM Loading: Didn't work at all in the release build (only debug mode worked). Many more fixes to the loader code to also load PSMs from the game Sinaria. Furthermore, effect conversion seems to be about right now.
[Fix] XM Compatibility: Volume command Ux should not enable Vibrato at all, it only sets the vibrato speed
[Fix] XM Compatibility: Pxy effect was too deep
[Imp] XM Loading: Detect MPT-made XMs more reliably
[Imp] XM Loading: Make XMs with strange pattern header sizes load correctly (removed some code that was there to make really, really broken XMs load - would this work at all?)
[Imp] XM Saveing: Include version number in "made with" string.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_psm.cpp
trunk/OpenMPT/soundlib/Load_xm.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
Modified: trunk/OpenMPT/soundlib/Load_psm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_psm.cpp 2009-08-22 22:47:59 UTC (rev 338)
+++ trunk/OpenMPT/soundlib/Load_psm.cpp 2009-08-23 21:07:17 UTC (rev 339)
@@ -3,17 +3,19 @@
* Authors: Johannes Schultz
*
* This is partly based on http://www.shikadi.net/moddingwiki/ProTracker_Studio_Module
- * and partly reverse-engineered.
+ * and partly reverse-engineered. Also thanks to the author of foo_dumb, the source code
+ * gave me a few clues. :)
*
* What's playing?
- * - Epic Pinball - Seems to be working perfectly with linear freq slides enabled
+ * - Epic Pinball - Perfect! (the old tunes in PSM16 format are not supported)
* - Extreme Pinball - Default tempo / speed / restart position of subtunes is missing.
* I'm using the last default values, restart position is still completely missing
- * - Jazz Jackrabbit - Hmm, I don't like some of the portas (BONUS.PSM - the guitar portamento is too "deep"), but apart from that it's great.
+ * - Jazz Jackrabbit - Perfect!
* - One Must Fall! - Perfect! (I modelled the volume slide and portamento conversion after this, as I got the original MTM files)
* - Silverball - Currently not supported (old PSM16 format)
+ * - Sinaria - Seems to work more or less (never played the game, so I can't really tell...)
*
- * Effect conversion should be about right, however I have my doubts wheter linear freq slides are used or not.
+ * Effect conversion should be about right...
*/
#include "stdafx.h"
@@ -36,44 +38,52 @@
};
-struct PSMSAMPLEHEADERTEST // apparently, this is wrong.
+struct PSMSAMPLEHEADER // Regular sample header
{
- CHAR sampleFormat[9];
+ BYTE flags;
+ CHAR fileName[8]; // Filename of the original module (without extension)
DWORD sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal)
CHAR sampleName[33];
CHAR unknown1[6]; // 00 00 00 00 00 FF
WORD sampleNumber;
+ DWORD sampleLength;
DWORD loopStart;
- CHAR loop; // 1 = loop
- CHAR unknown2[3]; // 00 00 00 00 00 FF
DWORD loopEnd; // FF FF FF FF = end of sample
WORD unknown3;
- CHAR defaultVolume;
+ BYTE defaultVolume;
DWORD unknown4;
WORD C5Freq;
- CHAR padding[21]; // 00 ... 00
+ CHAR unknown5[21]; // 00 ... 00
};
-struct PSMSAMPLEHEADER // Use this instead
+struct PSMSAMPLEHEADERSINARIA // Sinaria sample header
{
BYTE flags;
- CHAR fileName[8];
- DWORD sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal)
+ CHAR fileName[8]; // Filename of the original module (without extension)
+ CHAR sampleID[8]; // INS0...INS99999
CHAR sampleName[33];
CHAR unknown1[6]; // 00 00 00 00 00 FF
WORD sampleNumber;
DWORD sampleLength;
DWORD loopStart;
- DWORD loopEnd; // FF FF FF FF = end of sample
+ DWORD loopEnd;
WORD unknown3;
- CHAR defaultVolume;
- DWORD unknown4;
+ BYTE unknown4;
+ BYTE defaultVolume;
+ DWORD unknown5;
WORD C5Freq;
- CHAR unknown5[21]; // 00 ... 00
+ CHAR unknown6[16]; // 00 ... 00
};
-
#pragma pack()
+BYTE convert_psm_effect(BYTE param, bool bIsSinaria)
+{
+ if(bIsSinaria)
+ return param;
+ else
+ return (param >> 2);
+}
+
bool CSoundFile::ReadPSM(const LPCBYTE lpStream, const DWORD dwMemLength)
//-----------------------------------------------------------------------
{
@@ -81,6 +91,7 @@
if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false;
DWORD dwMemPos = 0;
+ bool bIsSinaria = false; // The game "Sinaria" uses a slightly modified PSM structure
ASSERT_CAN_READ(12);
PSMHEADER shdr;
@@ -92,7 +103,7 @@
// Yep, this seems to be a valid file.
m_nType = MOD_TYPE_PSM;
- m_dwSongFlags |= SONG_LINEARSLIDES; // Seems to be correct for Epic Pinball and Jazz Jackrabbit?
+ //m_dwSongFlags |= SONG_LINEARSLIDES; // TODO
m_nChannels = 0;
dwMemPos += 12;
@@ -137,10 +148,11 @@
// Pattern ID (something like "P0 " or "P13 ") follows
if(memcmp(lpStream + dwMemPos + 4, "P", 1)) return false;
+ if(!memcmp(lpStream + dwMemPos + 4, "PATT", 4)) bIsSinaria = true;
char patternID[4];
- memcpy(patternID, lpStream + dwMemPos + 5, 3);
+ memcpy(patternID, lpStream + dwMemPos + 5 + (bIsSinaria ? 3 : 0), 3);
patternID[3] = 0;
- patternOffsets.push_back(dwMemPos + 8);
+ patternOffsets.push_back(dwMemPos + 8 + (bIsSinaria ? 4 : 0));
patternIDs.push_back(atoi(patternID));
numPatterns++;
@@ -179,25 +191,22 @@
CHAR cDate[7];
memcpy(cDate, lpStream + dwChunkPos, 6);
cDate[6] = 0;
- sComment += "\r\nDate: ";
+ sComment += " - Date: ";
sComment += cDate;
break;
case 0x484C504F: // "OPLH" - Order list, channel + module settings
{
if(subChunkSize < 9) return false;
- // First byte = "Memory alloc, roughly ordlen + 10, if too small, song freezes"
- if(LittleEndian(*(DWORD *)(lpStream + dwChunkPos + 1)) != 0xFF000C00 // "Something"
- || LittleEndian(*(DWORD *)(lpStream + dwChunkPos + 5)) != 0x00010000) // "Something"
- return false;
+ // First two bytes = "Memory alloc, roughly ordlen + 10, if too small, song freezes"
// Now, the interesting part begins!
- DWORD dwSettingsOffset = dwChunkPos + 9;
+ DWORD dwSettingsOffset = dwChunkPos + 2;
while(dwSettingsOffset - dwChunkPos + 1 < subChunkSize)
{
switch(lpStream[dwSettingsOffset])
{
- case 0x00: // Seems to be the End item
+ case 0x00: // End
dwSettingsOffset += 1;
break;
@@ -207,7 +216,7 @@
for(PATTERNINDEX i = 0; i < patternIDs.size(); i++)
{
char patternID[4];
- memcpy(patternID, lpStream + dwSettingsOffset + 2, 3);
+ memcpy(patternID, lpStream + dwSettingsOffset + 2 + (bIsSinaria ? 3 : 0), 3);
patternID[3] = 0;
DWORD nPattern = atoi(patternID);
if(patternIDs[i] == nPattern)
@@ -216,25 +225,29 @@
break;
}
}
- dwSettingsOffset += 5;
+ dwSettingsOffset += 5 + (bIsSinaria ? 4 : 0);
break;
case 0x04:
/* It looks like the 2nd number of this chunk could be the restart position,
where position = ((number < 15) ? 0 : (number - 15)) */
+
+ //uint32 pos = lpStream[dwSettingsOffset + 1] | (lpStream[dwSettingsOffset + 2] << 8);
+
+ // NOTE: This should not be global! (Extreme Pinball!!!)
#ifdef DEBUG
{
char s[32];
wsprintf(s, " - restart %d", (lpStream[dwSettingsOffset + 1] < 15) ? 0 : lpStream[dwSettingsOffset + 1] - 15);
sComment += s;
- dwSettingsOffset += 3;
}
#endif
+ dwSettingsOffset += 3;
break;
case 0x07: // Default Speed
if(dwSettingsOffset - dwChunkPos + 2 > subChunkSize) break;
- // NOTE: This should not be global! (Extreme Pinball!!!)
+ // Same note as above!
m_nDefaultSpeed = lpStream[dwSettingsOffset + 1];
dwSettingsOffset += 2;
break;
@@ -246,19 +259,49 @@
dwSettingsOffset += 2;
break;
- case 0x0D: // This is a channel header
+ case 0x0C: // Sample map table (???)
+ if(dwSettingsOffset - dwChunkPos + 7 > subChunkSize) break;
+
+ if (lpStream[dwSettingsOffset + 1] != 0x00 || lpStream[dwSettingsOffset + 2] != 0xFF ||
+ lpStream[dwSettingsOffset + 3] != 0x00 || lpStream[dwSettingsOffset + 4] != 0x00 ||
+ lpStream[dwSettingsOffset + 5] != 0x01 || lpStream[dwSettingsOffset + 6] != 0x00)
+ return false;
+ dwSettingsOffset += 7;
+ break;
+
+ case 0x0D: // Channel panning table
if(dwSettingsOffset - dwChunkPos + 4 > subChunkSize) break;
- ChnSettings[min(lpStream[dwSettingsOffset + 1], pSong->numChannels)].nPan = lpStream[dwSettingsOffset + 2];
- // Last byte: "either 0, 2 or 4 (Some sort of priority?)"
+
+ {
+ CHANNELINDEX nChn = min(lpStream[dwSettingsOffset + 1], pSong->numChannels);
+ switch(lpStream[dwSettingsOffset + 3])
+ {
+ case 0:
+ ChnSettings[nChn].nPan = lpStream[dwSettingsOffset + 2];
+ break;
+
+ case 2:
+ ChnSettings[nChn].nPan = 128;
+ ChnSettings[nChn].dwFlags |= CHN_SURROUND;
+ break;
+
+ case 4:
+ ChnSettings[nChn].nPan = 128;
+ break;
+
+ }
+ }
dwSettingsOffset += 4;
break;
- case 0x0E: // Unknown - "0E <ChnID> FF"
+ case 0x0E: // Channel volume table
if(dwSettingsOffset - dwChunkPos + 3 > subChunkSize) break;
+ ChnSettings[min(lpStream[dwSettingsOffset + 1], pSong->numChannels)].nVolume = (lpStream[dwSettingsOffset + 2] >> 2) + 1;
+
dwSettingsOffset += 3;
break;
- default: // How the hell should this happen? I've listened through all existing (original) PSM files. :)
+ default: // How the hell should this happen? I've listened through almost all existing (original) PSM files. :)
CString s;
s.Format("Please report to the OpenMPT team: Unknown chunk %d found at position %d (in the OPLH chunk of this PSM file)", lpStream[dwSettingsOffset], dwSettingsOffset);
MessageBox(NULL, s, TEXT("OpenMPT PSM import"), MB_ICONERROR);
@@ -271,6 +314,29 @@
}
break;
+ case 0x4E415050: // PPAN - Channel panning table (used in Sinaria)
+ if(subChunkSize & 1) return false;
+ for(DWORD i = 0; i < subChunkSize; i += 2)
+ {
+ if((i >> 1) >= m_nChannels) break;
+ switch(lpStream[dwChunkPos + i])
+ {
+ case 0:
+ ChnSettings[i >> 1].nPan = lpStream[dwChunkPos + i + 1] - 128;
+ break;
+
+ case 2:
+ ChnSettings[i >> 1].nPan = 128;
+ ChnSettings[i >> 1].dwFlags |= CHN_SURROUND;
+ break;
+
+ case 4:
+ ChnSettings[i >> 1].nPan = 128;
+ break;
+ }
+ }
+ break;
+
case 0x54544150: // PATT - Pattern list
// We don't really need this.
break;
@@ -291,7 +357,7 @@
break;
case 0x504D5344: // DSMP - Samples
-
+ if(!bIsSinaria)
{
if(chunkSize < sizeof(PSMSAMPLEHEADER)) return false;
PSMSAMPLEHEADER *pSample = (PSMSAMPLEHEADER *)(lpStream + dwMemPos);
@@ -310,11 +376,34 @@
Samples[smp].nPan = 128;
Samples[smp].nVolume = (pSample->defaultVolume + 1) << 1;
Samples[smp].uFlags = (pSample->flags & 0x80) ? CHN_LOOP : 0;
- if(Samples[smp].nLoopStart > 0) Samples[smp].nLoopStart--;
if(Samples[smp].nLoopEnd == 0xFFFFFF) Samples[smp].nLoopEnd = Samples[smp].nLength;
// Delta-encoded samples
ReadSample(&Samples[smp], RS_PCM8D, (LPCSTR)(lpStream + dwMemPos + sizeof(PSMSAMPLEHEADER)), Samples[smp].nLength);
+ } else
+ {
+ // Sinaria uses a slightly different sample header
+ if(chunkSize < sizeof(PSMSAMPLEHEADERSINARIA)) return false;
+ PSMSAMPLEHEADERSINARIA *pSample = (PSMSAMPLEHEADERSINARIA *)(lpStream + dwMemPos);
+ SAMPLEINDEX smp = (SAMPLEINDEX)(LittleEndianW(pSample->sampleNumber) + 1);
+ m_nSamples = max(m_nSamples, smp);
+ memcpy(m_szNames[smp], pSample->sampleName, 31);
+ m_szNames[smp][31] = 0;
+ memcpy(Samples[smp].filename, pSample->fileName, 8);
+ Samples[smp].filename[8] = 0;
+
+ Samples[smp].nGlobalVol = 0x40;
+ Samples[smp].nC5Speed = LittleEndianW(pSample->C5Freq);
+ Samples[smp].nLength = LittleEndian(pSample->sampleLength);
+ Samples[smp].nLoopStart = LittleEndian(pSample->loopStart);
+ Samples[smp].nLoopEnd = LittleEndian(pSample->loopEnd);
+ Samples[smp].nPan = 128;
+ Samples[smp].nVolume = (pSample->defaultVolume + 1) << 1;
+ Samples[smp].uFlags = (pSample->flags & 0x80) ? CHN_LOOP : 0;
+ if(Samples[smp].nLoopEnd == 0xFFFFFF) Samples[smp].nLoopEnd = Samples[smp].nLength;
+
+ // Delta-encoded samples
+ ReadSample(&Samples[smp], RS_PCM8D, (LPCSTR)(lpStream + dwMemPos + sizeof(PSMSAMPLEHEADERSINARIA)), Samples[smp].nLength);
}
break;
@@ -369,10 +458,16 @@
if(dwRowOffset + 1 > dwMemLength) return false;
// Note present
BYTE bNote = lpStream[dwRowOffset];
- if(bNote == 0xFF)
- bNote = NOTE_NOTECUT;
- else
- bNote = (bNote & 0x0F) + 12 * (bNote >> 4) + 13;
+ if(!bIsSinaria)
+ {
+ if(bNote == 0xFF)
+ bNote = NOTE_NOTECUT;
+ else
+ bNote = (bNote & 0x0F) + 12 * (bNote >> 4) + 13;
+ } else
+ {
+ bNote += 36;
+ }
m->note = bNote;
dwRowOffset++;
}
@@ -423,23 +518,23 @@
// Portamento
case 0x0B: // fine portamento up
command = CMD_PORTAMENTOUP;
- param = 0xF0 | (param >> 1);
+ param = 0xF0 | convert_psm_effect(param, bIsSinaria);
break;
case 0x0C: // portamento up
command = CMD_PORTAMENTOUP;
- param >>= 1;
+ param = convert_psm_effect(param, bIsSinaria);
break;
case 0x0D: // fine portamento down
command = CMD_PORTAMENTODOWN;
- param = 0xF0 | (param >> 1);
+ param = 0xF0 | convert_psm_effect(param, bIsSinaria);
break;
case 0x0E: // portamento down
command = CMD_PORTAMENTODOWN;
- param >>= 1;
+ param = convert_psm_effect(param, bIsSinaria);
break;
case 0x0F: // tone portamento
command = CMD_TONEPORTAMENTO;
- param >>= 2;
+ param = convert_psm_effect(param, bIsSinaria);
break;
case 0x11: // glissando control
command = CMD_S3MCMDEX;
@@ -502,6 +597,7 @@
case 0x33: // position jump
command = CMD_POSITIONJUMP;
param >>= 1;
+ dwRowOffset += 1;
break;
case 0x34: // pattern break
command = CMD_PATTERNBREAK;
@@ -543,8 +639,11 @@
break;
default:
+ #ifdef DEBUG
ASSERT(false);
- //command = CMD_NONE;
+ #else
+ command = CMD_NONE;
+ #endif
break;
}
Modified: trunk/OpenMPT/soundlib/Load_xm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-08-22 22:47:59 UTC (rev 338)
+++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-08-23 21:07:17 UTC (rev 339)
@@ -109,7 +109,7 @@
if(lpStream[17 + i] == 0) bProbablyMadeWithModPlug = true;
if (!memcmp((LPCSTR)lpStream + 0x26, "FastTracker v2.00 ", 20) && bProbablyMadeWithModPlug) bMadeWithModPlug = true;
- if (!memcmp((LPCSTR)lpStream + 0x26, "Open ModPlug Tracker", 20)) bMadeWithModPlug = true;
+ if (!memcmp((LPCSTR)lpStream + 0x26, "OpenMPT ", 8)) bMadeWithModPlug = true;
dwHdrSize = LittleEndian(*((DWORD *)(lpStream+60)));
norders = LittleEndianW(*((WORD *)(lpStream+64)));
@@ -180,20 +180,20 @@
UINT ipatmap = pattern_map[ipat];
DWORD dwSize = 0;
WORD rows=64, packsize=0;
- dwSize = LittleEndian(*((DWORD *)(lpStream+dwMemPos)));
- while ((dwMemPos + dwSize >= dwMemLength) || (dwSize & 0xFFFFFF00))
+ dwSize = LittleEndian(*((DWORD *)(lpStream + dwMemPos)));
+ /*while ((dwMemPos + dwSize >= dwMemLength) || (dwSize & 0xFFFFFF00))
{
if (dwMemPos + 4 >= dwMemLength) break;
dwMemPos++;
dwSize = LittleEndian(*((DWORD *)(lpStream+dwMemPos)));
- }
- rows = LittleEndianW(*((WORD *)(lpStream+dwMemPos+5)));
+ }*/
+ rows = LittleEndianW(*((WORD *)(lpStream + dwMemPos + 5)));
// -> CODE#0008
// -> DESC="#define to set pattern size"
// if ((!rows) || (rows > 256)) rows = 64;
if ((!rows) || (rows > MAX_PATTERN_ROWS)) rows = 64;
// -> BEHAVIOUR_CHANGE#0008
- packsize = LittleEndianW(*((WORD *)(lpStream+dwMemPos+7)));
+ packsize = LittleEndianW(*((WORD *)(lpStream + dwMemPos + 7)));
if (dwMemPos + dwSize + 4 > dwMemLength) return true;
dwMemPos += dwSize;
if (dwMemPos + packsize > dwMemLength) return true;
@@ -694,9 +694,9 @@
fwrite("Extended Module: ", 17, 1, f);
fwrite(m_szNames[0], 20, 1, f);
s[0] = 0x1A;
- lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "Open ModPlug Tracker");
- s[21] = 0x04;
- s[22] = 0x01;
+ lstrcpy((LPSTR)&s[1], (nPacking) ? "MOD Plugin packed " : "OpenMPT " MPT_VERSION_STR " ");
+ s[21] = 0x04; // Version number
+ s[22] = 0x01; // XM Format v1.04
fwrite(&s[0], 23, 1, f);
// Writing song header
memset(&header, 0, sizeof(header));
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-08-22 22:47:59 UTC (rev 338)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-08-23 21:07:17 UTC (rev 339)
@@ -1420,7 +1420,10 @@
break;
case VOLCMD_VIBRATOSPEED:
- Vibrato(pChn, vol << 4);
+ if(IsCompatibleMode(TRK_FASTTRACKER2))
+ pChn->nVibratoSpeed = vol & 0x0F;
+ else
+ Vibrato(pChn, vol << 4);
break;
case VOLCMD_VIBRATODEPTH:
@@ -2386,6 +2389,8 @@
{
if (param & 0x0F) nPanSlide = -(int)((param & 0x0F) << 2);
else nPanSlide = (int)((param & 0xF0) >> 2);
+ if(IsCompatibleMode(TRK_FASTTRACKER2))
+ nPanSlide >>= 2;
}
}
if (nPanSlide)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-08-26 22:04:33
|
Revision: 345
http://modplug.svn.sourceforge.net/modplug/?rev=345&view=rev
Author: saga-games
Date: 2009-08-26 22:04:14 +0000 (Wed, 26 Aug 2009)
Log Message:
-----------
[Imp] IT Compatibility: More improvements to Vibrato, Tremolo and Panbrello. Using the tables from IT_TECH.TXT.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndmix.cpp
trunk/OpenMPT/soundlib/Tables.cpp
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-08-26 20:40:27 UTC (rev 344)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-08-26 22:04:14 UTC (rev 345)
@@ -717,7 +717,7 @@
}
pChn->nPos = 0;
pChn->nPosLo = 0;
- if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0;
+ if (pChn->nVibratoType < 4) pChn->nVibratoPos = ((!IsCompatibleMode(TRK_IMPULSETRACKER)) && (m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))) ? 0x10 : 0;
if(!IsCompatibleMode(TRK_IMPULSETRACKER) && pChn->nTremoloType < 4) pChn->nTremoloPos = 0;
}
if (pChn->nPos >= pChn->nLength) pChn->nPos = pChn->nLoopStart;
@@ -1859,6 +1859,7 @@
// IMF Commands
case CMD_NOTESLIDEUP:
NoteSlide(pChn, param, 1);
+ break;
case CMD_NOTESLIDEDOWN:
NoteSlide(pChn, param, -1);
break;
Modified: trunk/OpenMPT/soundlib/Sndmix.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-08-26 20:40:27 UTC (rev 344)
+++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-08-26 22:04:14 UTC (rev 345)
@@ -985,10 +985,10 @@
// Tremolo
if (pChn->dwFlags & CHN_TREMOLO)
{
- UINT trempos = pChn->nTremoloPos & 0x3F;
+ UINT trempos = pChn->nTremoloPos;
if (vol > 0 || IsCompatibleMode(TRK_IMPULSETRACKER))
{
- int tremattn = (m_nType & MOD_TYPE_XM) ? 5 : 6;
+ const int tremattn = (m_nType & MOD_TYPE_XM || IsCompatibleMode(TRK_IMPULSETRACKER)) ? 5 : 6;
switch (pChn->nTremoloType & 0x03)
{
case 1:
@@ -1000,7 +1000,7 @@
case 3:
//IT compatibility 19. Use random values
if(IsCompatibleMode(TRK_IMPULSETRACKER))
- vol += (((rand() & 0xFF) - 0x7F) * (int)pChn->nTremoloDepth) >> tremattn;
+ vol += (((rand() & 0x7F) - 0x40) * (int)pChn->nTremoloDepth) >> tremattn;
else
vol += (ModRandomTable[trempos] * (int)pChn->nTremoloDepth) >> tremattn;
break;
@@ -1010,7 +1010,10 @@
}
if ((m_nTickCount) || ((m_nType & (MOD_TYPE_STM|MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
{
- pChn->nTremoloPos = (pChn->nTremoloPos + pChn->nTremoloSpeed) & 0x3F;
+ if(IsCompatibleMode(TRK_IMPULSETRACKER))
+ pChn->nTremoloPos = (pChn->nTremoloPos + 4 * pChn->nTremoloSpeed) & 0xFF;
+ else
+ pChn->nTremoloPos = (pChn->nTremoloPos + pChn->nTremoloSpeed) & 0x3F;
}
}
@@ -1340,20 +1343,20 @@
switch (pChn->nVibratoType & 0x03)
{
case 1:
- vdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITRampDownTable[(vibpos + 48) % 64] : ModRampDownTable[vibpos];
+ vdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITRampDownTable[vibpos] : ModRampDownTable[vibpos];
break;
case 2:
- vdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITSquareTable[(vibpos + 48) % 64] : ModSquareTable[vibpos];
+ vdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITSquareTable[vibpos] : ModSquareTable[vibpos];
break;
case 3:
//IT compatibility 19. Use random values
if(IsCompatibleMode(TRK_IMPULSETRACKER))
- vdelta = (rand() & 0xFF) - 0x7F;
+ vdelta = (rand() & 0x7F) - 0x40;
else
vdelta = ModRandomTable[vibpos];
break;
default:
- vdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITSinusTable[(vibpos + 48) % 64] : ModSinusTable[vibpos];
+ vdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITSinusTable[vibpos] : ModSinusTable[vibpos];
}
if(m_nType == MOD_TYPE_MPT && pChn->pModInstrument && pChn->pModInstrument->pTuning)
@@ -1369,7 +1372,22 @@
}
else //Original behavior
{
- UINT vdepth = ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT))) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) ? 6 : 7;
+ UINT vdepth;
+ if(IsCompatibleMode(TRK_IMPULSETRACKER))
+ {
+ if(m_dwSongFlags & SONG_ITOLDEFFECTS)
+ {
+ vdepth = 5;
+ vdelta = -vdelta;
+ } else
+ {
+ vdepth = 6;
+ }
+ }
+ else
+ {
+ vdepth = ((!(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT))) || (m_dwSongFlags & SONG_ITOLDEFFECTS)) ? 6 : 7;
+ }
vdelta = (vdelta * (int)pChn->nVibratoDepth) >> vdepth;
if ((m_dwSongFlags & SONG_LINEARSLIDES) && (m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)))
{
@@ -1385,20 +1403,24 @@
if (l & 0x03) vdelta += _muldiv(period, FineLinearSlideUpTable[l & 0x03], 0x10000) - period;
}
}
- if(IsCompatibleMode(TRK_ALLTRACKERS))
- period -= vdelta;
- else
- period += vdelta;
+ period += vdelta;
}
if ((m_nTickCount) || ((m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) && (!(m_dwSongFlags & SONG_ITOLDEFFECTS))))
{
- pChn->nVibratoPos = (pChn->nVibratoPos + pChn->nVibratoSpeed) & 0x3F;
+ if(IsCompatibleMode(TRK_IMPULSETRACKER))
+ pChn->nVibratoPos = (vibpos + 4 * pChn->nVibratoSpeed) & 0xFF;
+ else
+ pChn->nVibratoPos = (vibpos + pChn->nVibratoSpeed) & 0x3F;
}
}
// Panbrello
if (pChn->dwFlags & CHN_PANBRELLO)
{
- UINT panpos = ((pChn->nPanbrelloPos+0x10) >> 2) & 0x3F;
+ UINT panpos;
+ if(IsCompatibleMode(TRK_IMPULSETRACKER))
+ panpos = pChn->nPanbrelloPos & 0xFF;
+ else
+ panpos = ((pChn->nPanbrelloPos + 0x10) >> 2) & 0x3F;
LONG pdelta;
switch (pChn->nPanbrelloType & 0x03)
{
@@ -1411,7 +1433,7 @@
case 3:
//IT compatibility 19. Use random values
if(IsCompatibleMode(TRK_IMPULSETRACKER))
- pdelta = (rand() & 0xFF) - 0x7F;
+ pdelta = (rand() & 0x7f) - 0x40;
else
pdelta = ModRandomTable[panpos];
break;
@@ -1419,7 +1441,7 @@
pdelta = IsCompatibleMode(TRK_IMPULSETRACKER) ? ITSinusTable[panpos] : ModSinusTable[panpos];
}
pChn->nPanbrelloPos += pChn->nPanbrelloSpeed;
- pdelta = ((pdelta * (int)pChn->nPanbrelloDepth) + 2) >> (IsCompatibleMode(TRK_IMPULSETRACKER) ? 4 : 3);
+ pdelta = ((pdelta * (int)pChn->nPanbrelloDepth) + 2) >> 3;
pdelta += pChn->nRealPan;
pChn->nRealPan = CLAMP(pdelta, 0, 256);
Modified: trunk/OpenMPT/soundlib/Tables.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Tables.cpp 2009-08-26 20:40:27 UTC (rev 344)
+++ trunk/OpenMPT/soundlib/Tables.cpp 2009-08-26 22:04:14 UTC (rev 345)
@@ -154,33 +154,69 @@
42,-34,89,-4,-51,-72,21,-29,112,123,84,-101,-92,98,-54,-95
};
-// Impulse Tracker tables
+// Impulse Tracker tables (ITTECH.TXT)
// Sinus table
-short int ITSinusTable[64] =
+short int ITSinusTable[256] =
{
- 0,12,25,37,49,60,71,81,90,98,106,112,117,122,125,126,
- 127,126,125,122,117,112,106,98,90,81,71,60,49,37,25,12,
- 0,-12,-25,-37,-49,-60,-71,-81,-90,-98,-106,-112,-117,-122,-125,-126,
- -127,-126,-125,-122,-117,-112,-106,-98,-90,-81,-71,-60,-49,-37,-25,-12
+ 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
+ 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
+ 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
+ 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
+ 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
+ 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
+ 0, -2, -3, -5, -6, -8, -9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
+ -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
+ -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
+ -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
+ -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
+ -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
+ -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
+ -24,-23,-22,-20,-19,-17,-16,-14,-12,-11, -9, -8, -6, -5, -3, -2,
};
// Triangle wave table (ramp down)
-short int ITRampDownTable[64] =
+short int ITRampDownTable[256] =
{
- 127,123,119,115,111,107,103,99,95,91,87,83,79,75,71,67,
- 63,59,55,51,47,43,39,35,31,27,23,19,15,11,7,3,
- 0,-4,-8,-12,-16,-20,-24,-28,-32,-36,-40,-44,-48,-52,-56,-60,
- -64,-68,-72,-76,-80,-84,-88,-92,-96,-100,-104,-108,-112,-116,-120,-124
+ 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56,
+ 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48,
+ 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40,
+ 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32,
+ 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24,
+ 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16,
+ 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8,
+ 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0,
+ 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8,
+ -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16,
+ -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24,
+ -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32,
+ -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40,
+ -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48,
+ -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56,
+ -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64,
};
// Square wave table
-short int ITSquareTable[64] =
+short int ITSquareTable[256] =
{
- 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
// volume fade tables for Retrig Note:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-10-12 22:04:47
|
Revision: 397
http://modplug.svn.sourceforge.net/modplug/?rev=397&view=rev
Author: saga-games
Date: 2009-10-12 22:04:33 +0000 (Mon, 12 Oct 2009)
Log Message:
-----------
[Fix] Improvements to the "Invert Loop" effect (was only applied on rows with EFx)
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndfile.cpp
trunk/OpenMPT/soundlib/Sndfile.h
trunk/OpenMPT/soundlib/Sndmix.cpp
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-10-12 00:44:56 UTC (rev 396)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-10-12 22:04:33 UTC (rev 397)
@@ -34,6 +34,7 @@
extern signed char retrigTable1[16];
extern signed char retrigTable2[16];
extern short int ModRandomTable[64];
+extern BYTE ModEFxTable[16];
////////////////////////////////////////////////////////////
@@ -1869,10 +1870,11 @@
break;
}
+ // MOD Effect (called every row)
+ InvertLoop(&Chn[nChn]);
+ } // for(...) end
- }
-
// Navigation Effects
if(m_dwSongFlags & SONG_FIRSTTICK)
{
@@ -2522,8 +2524,12 @@
case 0xC0: NoteCut(nChn, param); break;
// EDx: Note Delay
// EEx: Pattern Delay
- // EFx: MOD: Invert Loop / Funk Repeat, XM: Set Active Midi Macro
- case 0xF0: pChn->nActiveMacro = param; break;
+ case 0xF0:
+ if((m_nType & MOD_TYPE_MOD) != 0) // MOD: Invert Loop
+ pChn->nEFxSpeed = param;
+ else // XM: Set Active Midi Macro
+ pChn->nActiveMacro = param;
+ break;
}
}
@@ -2679,6 +2685,25 @@
}
+inline void CSoundFile::InvertLoop(MODCHANNEL *pChn)
+//--------------------------------------------------
+{
+ // EFx implementation for MOD files (PT 1.1A and up: Invert Loop)
+ // This effect trashes samples.
+ if((m_nType & MOD_TYPE_MOD) == 0 || pChn->nEFxSpeed == 0) return;
+
+ pChn->nEFxDelay += ModEFxTable[pChn->nEFxSpeed];
+ if(pChn->nEFxDelay < 0x80) return;
+ pChn->nEFxDelay = 0;
+ if (++pChn->nEFxOffset >= pChn->nLoopEnd - pChn->nLoopStart)
+ pChn->nEFxOffset = 0;
+
+ // TRASH IT!!! (Yes, the sample!)
+ if(pChn->pSample != nullptr && (pChn->dwFlags & CHN_LOOP))
+ pChn->pSample[pChn->nLoopStart + pChn->nEFxOffset] = ~pChn->pSample[pChn->nLoopStart + pChn->nEFxOffset];
+}
+
+
void CSoundFile::ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param)
//---------------------------------------------------------------------------
{
@@ -3797,6 +3822,3 @@
pChn->m_CalculateFreq = true;
}
-
-
-
Modified: trunk/OpenMPT/soundlib/Sndfile.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.cpp 2009-10-12 00:44:56 UTC (rev 396)
+++ trunk/OpenMPT/soundlib/Sndfile.cpp 2009-10-12 22:04:33 UTC (rev 397)
@@ -638,6 +638,7 @@
Chn[ich].dwFlags = ChnSettings[ich].dwFlags;
Chn[ich].nVolume = 256;
Chn[ich].nCutOff = 0x7F;
+ Chn[ich].nEFxSpeed = 0;
//IT compatibility 15. Retrigger
if(IsCompatibleMode(TRK_IMPULSETRACKER))
{
@@ -1467,6 +1468,7 @@
Chn[i].nRetrigCount = 0;
}
Chn[i].nTremorCount = 0;
+ Chn[i].nEFxSpeed = 0;
}
if(resetMask & 4)
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2009-10-12 00:44:56 UTC (rev 396)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2009-10-12 22:04:33 UTC (rev 397)
@@ -200,7 +200,7 @@
LONG nCutSwing, nResSwing;
LONG nRestorePanOnNewNote; //If > 0, nPan should be set to nRestorePanOnNewNote - 1 on new note. Used to recover from panswing.
UINT nOldGlobalVolSlide;
- DWORD nEFxOffset; // offset memory for either Funk Repeat or Invert Loop (EFx, .MOD only)
+ DWORD nEFxOffset; // offset memory for Invert Loop (EFx, .MOD only)
// 8-bit members
BYTE nRestoreResonanceOnNewNote; //Like above
BYTE nRestoreCutoffOnNewNote; //Like above
@@ -224,7 +224,7 @@
BYTE nRowCommand, nRowParam;
BYTE nLeftVU, nRightVU;
BYTE nActiveMacro, nFilterMode;
- BYTE nEFxDelay; // memory for either Funk Repeat or Invert Loop (EFx, .MOD only)
+ BYTE nEFxSpeed, nEFxDelay; // memory for Invert Loop (EFx, .MOD only)
uint16 m_RowPlugParam; //NOTE_PCs memory.
float m_nPlugParamValueStep; //rewbs.smoothVST
@@ -725,12 +725,12 @@
void WriteInstrumentPropertyForAllInstruments(__int32 code, __int16 size, FILE* f, MODINSTRUMENT* instruments[], UINT nInstruments);
void SaveExtendedInstrumentProperties(MODINSTRUMENT *instruments[], UINT nInstruments, FILE* f);
void SaveExtendedSongProperties(FILE* f);
- void LoadExtendedSongProperties(const MODTYPE modtype, LPCBYTE ptr, const LPCBYTE startpos, const size_t seachlimit, bool* pInterpretMptMade = NULL);
+ void LoadExtendedSongProperties(const MODTYPE modtype, LPCBYTE ptr, const LPCBYTE startpos, const size_t seachlimit, bool* pInterpretMptMade = false);
// Reads extended instrument properties(XM/IT/MPTM).
// If no errors occur and song extension tag is found, returns pointer to the beginning
// of the tag, else returns NULL.
- LPCBYTE LoadExtendedInstrumentProperties(const LPCBYTE pStart, const LPCBYTE pEnd, bool* pInterpretMptMade = NULL);
+ LPCBYTE LoadExtendedInstrumentProperties(const LPCBYTE pStart, const LPCBYTE pEnd, bool* pInterpretMptMade = false);
#endif // MODPLUG_NO_FILESAVE
// MOD Convert function
@@ -847,6 +847,7 @@
void ExtendedMODCommands(UINT nChn, UINT param);
void ExtendedS3MCommands(UINT nChn, UINT param);
void ExtendedChannelEffect(MODCHANNEL *, UINT param);
+ inline void InvertLoop(MODCHANNEL* pChn);
void ProcessMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0);
void ProcessSmoothMidiMacro(UINT nChn, LPCSTR pszMidiMacro, UINT param=0); //rewbs.smoothVST
void SetupChannelFilter(MODCHANNEL *pChn, bool bReset, int flt_modifier = 256) const;
Modified: trunk/OpenMPT/soundlib/Sndmix.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-10-12 00:44:56 UTC (rev 396)
+++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-10-12 22:04:33 UTC (rev 397)
@@ -78,7 +78,6 @@
extern signed char ft2VibratoTable[256]; // -64 .. +64
extern int MixSoundBuffer[MIXBUFFERSIZE*4];
extern int MixRearBuffer[MIXBUFFERSIZE*2];
-extern BYTE ModEFxTable[16];
#ifndef NO_REVERB
extern UINT gnReverbSend;
@@ -1692,24 +1691,6 @@
}
}
- // .MOD EFx implementation
- if((m_nType & MOD_TYPE_MOD) && pChn->nRowCommand == CMD_MODCMDEX && (pChn->nRowParam & 0xF0) == 0xF0)
- {
- pChn->nEFxDelay += ModEFxTable[pChn->nRowParam & 0x0F];
- if((pChn->dwFlags & CHN_LOOP) && (pChn->nEFxDelay & 0x80))
- {
- // invert loop code (PT 1.1A and up)
- pChn->nEFxDelay = 0;
-
- if (++pChn->nEFxOffset >= pChn->nLoopEnd - pChn->nLoopStart)
- pChn->nEFxOffset = 0;
-
- // TRASH IT!!! (Yes, the sample!)
- pChn->pSample[pChn->nLoopStart + pChn->nEFxOffset] = ~pChn->pSample[pChn->nLoopStart + pChn->nEFxOffset];
- }
- }
-
-
#ifdef MODPLUG_PLAYER
// Limit CPU -> > 80% -> don't ramp
if ((gnCPUUsage >= 80) && (!pChn->nRealVolume))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-11-06 17:48:58
|
Revision: 412
http://modplug.svn.sourceforge.net/modplug/?rev=412&view=rev
Author: saga-games
Date: 2009-11-06 17:48:42 +0000 (Fri, 06 Nov 2009)
Log Message:
-----------
[Fix] MOD Loader: 8Chn Startrekker modules ("FLT8") are loaded correctly now.
[Imp] MOD Playback: if PT1.x playback flag is set, 8xx and E8x panning commands are now ignored.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_mod.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
Modified: trunk/OpenMPT/soundlib/Load_mod.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mod.cpp 2009-11-03 09:42:38 UTC (rev 411)
+++ trunk/OpenMPT/soundlib/Load_mod.cpp 2009-11-06 17:48:42 UTC (rev 412)
@@ -214,9 +214,9 @@
#pragma pack()
-BOOL IsMagic(LPCSTR s1, LPCSTR s2)
+bool IsMagic(LPCSTR s1, LPCSTR s2)
{
- return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? TRUE : FALSE;
+ return ((*(DWORD *)s1) == (*(DWORD *)s2)) ? true : false;
}
@@ -246,6 +246,7 @@
if ((s[0]=='T') && (s[1]=='D') && (s[2]=='Z') && (s[3]>='4') && (s[3]<='9')) m_nChannels = s[3] - '0'; else
if (IsMagic(s,"16CN")) m_nChannels = 16; else
if (IsMagic(s,"32CN")) m_nChannels = 32; else m_nSamples = 15;
+ bool bFLT8 = IsMagic(s, "FLT8") ? true : false;
// Load Samples
nErr = 0;
dwTotalSampleLen = 0;
@@ -321,8 +322,24 @@
if (iord<norders) nbpbuggy = nbp;
}
if (i >= nbpbuggy2) nbpbuggy2 = i+1;
+
+ // from mikmod: if the file says FLT8, but the orderlist has odd numbers, it's probably really an FLT4
+ if(bFLT8 && (Order[iord] & 1))
+ {
+ m_nChannels = 4;
+ bFLT8 = false;
+ }
}
- for (UINT iend = norders; iend < 0x80; iend++) Order[iend] = Order.GetInvalidPatIndex();
+
+ if(bFLT8)
+ {
+ // FLT8 has only equal order items, so divide by two.
+ for(ORDERINDEX nOrd = 0; nOrd < Order.GetLength(); nOrd++)
+ Order[nOrd] >>= 1;
+ }
+
+ for(UINT iend = norders; iend < 0x80; iend++) Order[iend] = Order.GetInvalidPatIndex();
+
norders--;
m_nRestartPos = pMagic->nRestartPos;
if (m_nRestartPos >= 0x78) m_nRestartPos = 0;
@@ -352,27 +369,53 @@
// Setup channel pan positions and volume
SetupMODPanning();
- // Reading channels
- for (UINT ipat=0; ipat<nbp; ipat++)
+ const CHANNELINDEX nMaxChn = (bFLT8) ? 4 : m_nChannels; // 4 channels per pattern in FLT8 format.
+ if(bFLT8) nbp++; // as one logical pattern consists of two real patterns in FLT8 format, the highest pattern number has to be increased by one.
+
+ // Reading patterns
+ for (PATTERNINDEX ipat = 0; ipat < nbp; ipat++)
{
if (ipat < MAX_PATTERNS)
{
- if(Patterns.Insert(ipat, 64)) break;
- if (dwMemPos + m_nChannels * 256 > dwMemLength) break;
- MODCOMMAND *m = Patterns[ipat];
- LPCBYTE p = lpStream + dwMemPos;
- for (UINT j=m_nChannels*64; j; m++,p+=4,j--)
+ if (dwMemPos + nMaxChn * 256 > dwMemLength) break;
+
+ MODCOMMAND *m;
+ if(bFLT8)
{
- BYTE A0=p[0], A1=p[1], A2=p[2], A3=p[3];
- UINT n = ((((UINT)A0 & 0x0F) << 8) | (A1));
- if ((n) && (n != 0xFFF)) m->note = GetNoteFromPeriod(n << 2);
- m->instr = ((UINT)A2 >> 4) | (A0 & 0x10);
- m->command = A2 & 0x0F;
- m->param = A3;
- if ((m->command) || (m->param)) ConvertModCommand(m);
+ if((ipat & 1) == 0)
+ {
+ // only create "even" patterns
+ if(Patterns.Insert(ipat >> 1, 64)) break;
+ }
+ m = Patterns[ipat >> 1];
+ } else
+ {
+ if(Patterns.Insert(ipat, 64)) break;
+ m = Patterns[ipat];
}
+
+ const BYTE *p = lpStream + dwMemPos;
+ for(ROWINDEX nRow = 0; nRow < 64; nRow++)
+ {
+ if(bFLT8)
+ {
+ // FLT8: either write to channel 1 to 4 (even patterns) or 5 to 8 (odd patterns).
+ m = Patterns[ipat >> 1] + nRow * 8 + ((ipat & 1) ? 4 : 0);
+ }
+ for(CHANNELINDEX nChn = 0; nChn < nMaxChn; nChn++, m++, p += 4)
+ {
+ BYTE A0 = p[0], A1 = p[1], A2 = p[2], A3 = p[3];
+ UINT n = ((((UINT)A0 & 0x0F) << 8) | (A1));
+ if ((n) && (n != 0xFFF)) m->note = GetNoteFromPeriod(n << 2);
+ m->instr = ((UINT)A2 >> 4) | (A0 & 0x10);
+ m->command = A2 & 0x0F;
+ m->param = A3;
+ if ((m->command) || (m->param)) ConvertModCommand(m);
+
+ }
+ }
}
- dwMemPos += m_nChannels*256;
+ dwMemPos += nMaxChn * 256;
}
// Reading samples
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-03 09:42:38 UTC (rev 411)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-06 17:48:42 UTC (rev 412)
@@ -1670,6 +1670,7 @@
// Set 8-bit Panning
case CMD_PANNING8:
if (!(m_dwSongFlags & SONG_FIRSTTICK)) break;
+ if ((m_dwSongFlags & SONG_PT1XMODE)) break;
if (!(m_dwSongFlags & SONG_SURROUNDPAN)) pChn->dwFlags &= ~CHN_SURROUND;
if (m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT|MOD_TYPE_XM|MOD_TYPE_MOD|MOD_TYPE_MT2))
{
@@ -2504,7 +2505,7 @@
// E7x: Set Tremolo WaveForm
case 0x70: pChn->nTremoloType = param & 0x07; break;
// E8x: Set 4-bit Panning
- case 0x80: if(m_dwSongFlags & SONG_FIRSTTICK)
+ case 0x80: if((m_dwSongFlags & SONG_FIRSTTICK) && !(m_dwSongFlags & SONG_PT1XMODE))
{
//IT compatibility 20. (Panning always resets surround state)
if(IsCompatibleMode(TRK_ALLTRACKERS))
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-11-07 23:38:23
|
Revision: 416
http://modplug.svn.sourceforge.net/modplug/?rev=416&view=rev
Author: saga-games
Date: 2009-11-07 23:38:07 +0000 (Sat, 07 Nov 2009)
Log Message:
-----------
[Fix] A wrong #define was used in the plugin finding algorithm which broke plugin handling for instruments in some cases in the last revision.
[Fix] Various fixes to the MDL loader (taken from Schism Tracker)
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_mdl.cpp
trunk/OpenMPT/soundlib/Snd_defs.h
trunk/OpenMPT/soundlib/Snd_fx.cpp
Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mdl.cpp 2009-11-07 21:40:01 UTC (rev 415)
+++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2009-11-07 23:38:07 UTC (rev 416)
@@ -80,8 +80,30 @@
}
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; } break;
- case 0x20: if ((param & 0xF0) != 0xE0) { command = CMD_VOLUMESLIDE; if ((param & 0xF0) != 0xF0) param >>= 2; } 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 0x30: command = CMD_RETRIG; break;
case 0x40: command = CMD_TREMOLO; break;
case 0x50: command = CMD_TREMOR; break;
@@ -392,6 +414,10 @@
pIns->PanEnv.dwFlags |= ENV_ENABLED;
inspanenv[nins] = (ps[5] & 0x3F) + 1;
}
+
+ // taken from load_xm.cpp - seems to fix wakingup.mdl
+ if (!(pIns->VolEnv.dwFlags & ENV_ENABLED) && !pIns->nFadeOut)
+ pIns->nFadeOut = 8192;
}
}
dwPos += 34 + 14*lpStream[dwPos+1];
@@ -457,7 +483,6 @@
pSmp->nLoopStart = *((DWORD *)(p+4));
pSmp->nLoopEnd = pSmp->nLoopStart + *((DWORD *)(p+8));
if (pSmp->nLoopEnd > pSmp->nLoopStart) pSmp->uFlags |= CHN_LOOP;
- pSmp->nVolume = 256;
pSmp->nGlobalVol = 64;
if (p[13] & 0x01)
{
Modified: trunk/OpenMPT/soundlib/Snd_defs.h
===================================================================
--- trunk/OpenMPT/soundlib/Snd_defs.h 2009-11-07 21:40:01 UTC (rev 415)
+++ trunk/OpenMPT/soundlib/Snd_defs.h 2009-11-07 23:38:07 UTC (rev 416)
@@ -130,7 +130,7 @@
#define CHN_PINGPONGSUSTAIN 0x10
#define CHN_PANNING 0x20
#define CHN_STEREO 0x40
-#define CHN_PINGPONGFLAG 0x80 //When flag is on, bidiloop is processed backwards?
+#define CHN_PINGPONGFLAG 0x80 //When flag is on, sample is processed backwards
// Bits 8-31: Channel Flags
#define CHN_MUTE 0x100
#define CHN_KEYOFF 0x200
@@ -157,10 +157,10 @@
#define CHN_SYNCMUTE 0x40000000
// instrument envelope-specific flags
-#define ENV_LOOP 0x01 // env loop
-#define ENV_SUSTAIN 0x02 // env sustain
-#define ENV_CARRY 0x04 // env carry
-#define ENV_ENABLED 0x08 // env is enabled
+#define ENV_ENABLED 0x01 // env is enabled
+#define ENV_LOOP 0x02 // env loop
+#define ENV_SUSTAIN 0x04 // env sustain
+#define ENV_CARRY 0x08 // env carry
#define ENV_FILTER 0x10 // filter env enabled (this has to be combined with ENV_ENABLED in the pitch envelope's flags)
// instrument-specific flags
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-07 21:40:01 UTC (rev 415)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-07 23:38:07 UTC (rev 416)
@@ -3754,7 +3754,7 @@
UINT nPlugin=0;
if (pChn && pChn->pModInstrument) {
- if (respectMutes && pChn->pModSample && pChn->pModSample->uFlags&INS_MUTE) {
+ if (respectMutes && pChn->pModSample && (pChn->pModSample->uFlags & CHN_MUTE)) {
nPlugin = 0;
} else {
nPlugin = pChn->pModInstrument->nMixPlug;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-11-21 15:41:10
|
Revision: 420
http://modplug.svn.sourceforge.net/modplug/?rev=420&view=rev
Author: saga-games
Date: 2009-11-21 15:40:57 +0000 (Sat, 21 Nov 2009)
Log Message:
-----------
[Fix] When jumping around in a module, high offest value is also memorized
[Fix] XM Saver: +++ and --- orders are preserved when not using compatibility mode for now.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_xm.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
Modified: trunk/OpenMPT/soundlib/Load_xm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_xm.cpp 2009-11-20 13:04:34 UTC (rev 419)
+++ trunk/OpenMPT/soundlib/Load_xm.cpp 2009-11-21 15:40:57 UTC (rev 420)
@@ -770,6 +770,8 @@
if(Order[nOrd] >= nPatterns) nPatterns = Order[nOrd] + 1;
}
}
+ if(!bCompatibilityExport) nMaxOrds = Order.GetLengthTailTrimmed(); // should really be removed at some point
+
xmheader.orders = LittleEndianW((WORD)nMaxOrds);
xmheader.patterns = LittleEndianW((WORD)nPatterns);
xmheader.size = LittleEndian((DWORD)(xmheader.size + nMaxOrds));
@@ -793,7 +795,7 @@
// write order list (wihout +++ and ---, explained above)
for(ORDERINDEX nOrd = 0; nOrd < Order.GetLengthTailTrimmed(); nOrd++)
{
- if(Patterns.IsValidIndex(Order[nOrd]))
+ if(Patterns.IsValidIndex(Order[nOrd]) || !bCompatibilityExport)
{
BYTE nOrdval = static_cast<BYTE>(Order[nOrd]);
fwrite(&nOrdval, 1, sizeof(BYTE), f);
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-20 13:04:34 UTC (rev 419)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-21 15:40:57 UTC (rev 420)
@@ -261,6 +261,7 @@
// Pattern Delay
case CMD_S3MCMDEX:
if ((param & 0xF0) == 0x60) { nSpeedCount = param & 0x0F; break; } else
+ if ((param & 0xF0) == 0xA0) { pChn->nOldHiOffset = param & 0x0F; break; } else
if ((param & 0xF0) == 0xB0) { param &= 0x0F; param |= 0x60; }
case CMD_MODCMDEX:
if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-11-21 18:25:18
|
Revision: 421
http://modplug.svn.sourceforge.net/modplug/?rev=421&view=rev
Author: saga-games
Date: 2009-11-21 18:24:39 +0000 (Sat, 21 Nov 2009)
Log Message:
-----------
[Fix] When jumping around in a module, high offest value is also memorized in XM files now.
[Fix] XM Compatibility: Command X modplug extensions are now ignored in FT2 compat mode.
[Fix] IT Compatibility: IT files with empty sample slots will now FINALLY save correctly in Impulse Tracker.
[Fix] IT Compatibility: IT files with global volume 0 are now loaded correctly
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/Snd_fx.cpp
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2009-11-21 15:40:57 UTC (rev 420)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2009-11-21 18:24:39 UTC (rev 421)
@@ -965,18 +965,11 @@
SpaceToNullStringFixed(m_szNames[0], 26);
// Global Volume
- if (pifh->globalvol)
- {
- m_nDefaultGlobalVolume = pifh->globalvol << 1;
- if (!m_nDefaultGlobalVolume) m_nDefaultGlobalVolume = 256;
- if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
- }
+ m_nDefaultGlobalVolume = pifh->globalvol << 1;
+ if (m_nDefaultGlobalVolume > 256) m_nDefaultGlobalVolume = 256;
if (pifh->speed) m_nDefaultSpeed = pifh->speed;
m_nDefaultTempo = max(32, pifh->tempo); // tempo 31 is possible. due to conflicts with the rest of the engine, let's just clamp it to 32.
m_nSamplePreAmp = min(pifh->mv, 128);
- /*if (m_nSamplePreAmp<0x20) {
- m_nSamplePreAmp=100;
- }*/
// Reading Channels Pan Positions
for (int ipan=0; ipan</*MAX_BASECHANNELS*/64; ipan++) if (pifh->chnpan[ipan] != 0xFF) //Header only has room for settings for 64 chans...
@@ -1474,8 +1467,10 @@
static char autodetectITplaymode = -1;
if(GetType() == MOD_TYPE_IT)
{
+#ifdef MODPLUG_TRACKER
if(autodetectITplaymode == -1)
autodetectITplaymode = CMainFrame::GetPrivateProfileLong("Misc", "AutodetectITplaystyle", 1, theApp.GetConfigFileName());
+#endif
if(autodetectITplaymode)
{
@@ -2344,7 +2339,10 @@
flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S;
}
}
- itss.samplepointer = dwPos;
+ if ((psmp->pSample) && (psmp->nLength))
+ itss.samplepointer = dwPos;
+ else
+ itss.samplepointer = itss.flags = 0;
fseek(f, smppos[nsmp-1], SEEK_SET);
fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
fseek(f, dwPos, SEEK_SET);
@@ -2920,7 +2918,10 @@
itss.flags |= 0x02;
flags = RS_PCM16S;
}
- itss.samplepointer = dwPos;
+ if ((psmp->pSample) && (psmp->nLength))
+ itss.samplepointer = dwPos;
+ else
+ itss.samplepointer = itss.flags = 0;
fseek(f, smppos[nsmp-1], SEEK_SET);
fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f);
fseek(f, dwPos, SEEK_SET);
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-21 15:40:57 UTC (rev 420)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-11-21 18:24:39 UTC (rev 421)
@@ -271,6 +271,9 @@
else patloop[nChn] = dwElapsedTime;
}
break;
+ case CMD_XFINEPORTAUPDOWN:
+ if (((param & 0xF0) == 0xA0) && !IsCompatibleMode(TRK_FASTTRACKER2)) pChn->nOldHiOffset = param & 0x0F;
+ break;
}
if (!bAdjust) continue;
switch(command)
@@ -1761,7 +1764,8 @@
case 0x60:
case 0x70:
case 0x90:
- case 0xA0: ExtendedS3MCommands(nChn, param); break;
+ case 0xA0: if(!IsCompatibleMode(TRK_FASTTRACKER2)) ExtendedS3MCommands(nChn, param);
+ break;
}
break;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-12-13 15:28:16
|
Revision: 441
http://modplug.svn.sourceforge.net/modplug/?rev=441&view=rev
Author: saga-games
Date: 2009-12-13 15:28:07 +0000 (Sun, 13 Dec 2009)
Log Message:
-----------
[Fix] IT Compatibility: Fixes from SchismTracker: VolSwing, PanSwing, PPS
[Fix] XM Compatibility: Slightly improved Rxy behaviour.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndmix.cpp
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-12-11 23:39:57 UTC (rev 440)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-12-13 15:28:07 UTC (rev 441)
@@ -768,7 +768,7 @@
if(!IsCompatibleMode(TRK_IMPULSETRACKER))
{
//IT compatibility 15. Retrigger will not be reset (Tremor doesn't store anything here, so we just don't reset this as well)
- pChn->nRetrigCount = 0;
+ if(!IsCompatibleMode(TRK_FASTTRACKER2)) pChn->nRetrigCount = 0;
pChn->nTremorCount = 0;
}
if (bResetEnv)
@@ -785,15 +785,29 @@
// Volume Swing
if (pIns->nVolSwing)
{
- int d = ((LONG)pIns->nVolSwing * (LONG)((rand() & 0xFF) - 0x7F)) / 128;
- pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128);
+ if(IsCompatibleMode(TRK_IMPULSETRACKER))
+ {
+ double d = 2 * (((double) rand()) / RAND_MAX) - 1;
+ pChn->nVolSwing = d * pIns->nVolSwing / 100.0 * pChn->nVolume;
+ } else
+ {
+ int d = ((LONG)pIns->nVolSwing * (LONG)((rand() & 0xFF) - 0x7F)) / 128;
+ pChn->nVolSwing = (signed short)((d * pChn->nVolume + 1)/128);
+ }
}
// Pan Swing
if (pIns->nPanSwing)
{
- int d = ((LONG)pIns->nPanSwing * (LONG)((rand() & 0xFF) - 0x7F)) / 128;
- pChn->nPanSwing = (signed short)d;
- pChn->nRestorePanOnNewNote = pChn->nPan+1;
+ if(IsCompatibleMode(TRK_IMPULSETRACKER))
+ {
+ double d = 2 * (((double) rand()) / RAND_MAX) - 1;
+ pChn->nPanSwing = d * pIns->nPanSwing * 4;
+ } else
+ {
+ int d = ((LONG)pIns->nPanSwing * (LONG)((rand() & 0xFF) - 0x7F)) / 128;
+ pChn->nPanSwing = (signed short)d;
+ pChn->nRestorePanOnNewNote = pChn->nPan + 1;
+ }
}
// Cutoff Swing
if (pIns->nCutSwing)
@@ -2500,7 +2514,7 @@
// E4x: Set Vibrato WaveForm
case 0x40: pChn->nVibratoType = param & 0x07; break;
// E5x: Set FineTune
- case 0x50: if (m_nTickCount) break;
+ case 0x50: if(!(m_dwSongFlags & SONG_FIRSTTICK)) break;
pChn->nC5Speed = S3MFineTuneTable[param];
if (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))
pChn->nFineTune = param*2;
@@ -2536,7 +2550,11 @@
if((m_nType & MOD_TYPE_MOD) != 0) // MOD: Invert Loop
{
pChn->nEFxSpeed = param;
- if(m_dwSongFlags & SONG_FIRSTTICK) InvertLoop(pChn);
+ if(m_dwSongFlags & SONG_FIRSTTICK)
+ {
+ //if((pChn->nRowInstr != 0) && (m_nTickCount == 0)) pChn->nEFxOffset = 0; // reset offset (except when in pattern delay) TODO
+ InvertLoop(pChn);
+ }
}
else // XM: Set Active Midi Macro
{
@@ -2559,7 +2577,7 @@
// S1x: Set Glissando Control
case 0x10: pChn->dwFlags &= ~CHN_GLISSANDO; if (param) pChn->dwFlags |= CHN_GLISSANDO; break;
// S2x: Set FineTune
- case 0x20: if (m_nTickCount) break;
+ case 0x20: if(!(m_dwSongFlags & SONG_FIRSTTICK)) break;
pChn->nC5Speed = S3MFineTuneTable[param & 0x0F];
pChn->nFineTune = MOD2XMFineTune(param);
if (pChn->nPeriod) pChn->nPeriod = GetPeriodFromNote(pChn->nNote, pChn->nFineTune, pChn->nC5Speed);
@@ -2573,7 +2591,7 @@
// S6x: Pattern Delay for x frames
case 0x60: m_nFrameDelay = param; break;
// S7x: Envelope Control
- case 0x70: if (m_nTickCount) break;
+ case 0x70: if(!(m_dwSongFlags & SONG_FIRSTTICK)) break;
switch(param)
{
case 0:
@@ -3150,8 +3168,9 @@
if(m_dwSongFlags & SONG_FIRSTTICK)
{
- // FT2 bug: if a retrig (Rxy) occours together with a volume command, the first retrig interval is increased by one tick
- if(pChn->nRowVolCmd == VOLCMD_VOLUME) nRetrigCount = -1;
+ // here are some really stupid things FT2 does
+ if(pChn->nRowInstr > 0 && pChn->nRowNote == NOTE_NONE) nRetrigCount = 1;
+ if(pChn->nRowVolCmd == VOLCMD_VOLUME) nRetrigCount = -1; // not correct yet
if(pChn->nRowNote != NOTE_NONE && pChn->nRowNote <= GetModSpecifications().noteMax) nRetrigCount++;
}
if (nRetrigCount >= nRetrigSpeed)
@@ -3164,6 +3183,8 @@
}
} else
{
+ // old routines
+
if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT))
{
if (!nRetrigSpeed) nRetrigSpeed = 1;
Modified: trunk/OpenMPT/soundlib/Sndmix.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-12-11 23:39:57 UTC (rev 440)
+++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-12-13 15:28:07 UTC (rev 441)
@@ -1153,7 +1153,9 @@
// Pitch/Pan separation
if ((pIns->nPPS) && (pChn->nRealPan) && (pChn->nNote))
{
- int pandelta = (int)pChn->nRealPan + (int)((int)(pChn->nNote - pIns->nPPC - 1) * (int)pIns->nPPS) / (int)8;
+ // PPS value is 1/512, i.e. PPS=1 will adjust by 8/512 = 1/64 for each 8 semitones
+ // with PPS = 32 / PPC = C-5, E-6 will pan hard right (and D#6 will not)
+ int pandelta = (int)pChn->nRealPan + (int)((int)(pChn->nNote - pIns->nPPC - 1) * (int)pIns->nPPS) / (int)(IsCompatibleMode(TRK_IMPULSETRACKER) ? 4 : 8);
pChn->nRealPan = CLAMP(pandelta, 0, 256);
}
} else
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2009-12-25 12:00:44
|
Revision: 450
http://modplug.svn.sourceforge.net/modplug/?rev=450&view=rev
Author: saga-games
Date: 2009-12-25 12:00:26 +0000 (Fri, 25 Dec 2009)
Log Message:
-----------
[Fix] FT2 compatibility: Almost perfect arpeggio emulation (only a few notes are still wrong)
[Fix] FT2 compatibility: Rogue note delays
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndmix.cpp
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-12-23 19:56:16 UTC (rev 449)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2009-12-25 12:00:26 UTC (rev 450)
@@ -635,7 +635,7 @@
note = pIns->NoteMap[note-1];
}
// Key Off
- if (note >= 0x80)
+ if (note > NOTE_MAX)
{
// Key Off (+ Invalid Note for XM - TODO is this correct?)
if (note == NOTE_KEYOFF || !(m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT)))
@@ -664,7 +664,7 @@
if(bNewTuning)
{
- if(!bPorta || pChn->nNote == 0)
+ if(!bPorta || pChn->nNote == NOTE_NONE)
pChn->nPortamentoDest = 0;
else
{
@@ -1268,6 +1268,12 @@
pChn->nVolume = 0;
note = instr = 0;
}
+
+ // XM: Rogue note delays cause retrig
+ if ((note == NOTE_NONE) && IsCompatibleMode(TRK_FASTTRACKER2) && !(m_dwSongFlags & SONG_FIRSTTICK))
+ {
+ note = pChn->nNote - pChn->nTranspose;
+ }
}
if ((!note) && (instr)) //Case: instrument with no note data.
{
Modified: trunk/OpenMPT/soundlib/Sndmix.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndmix.cpp 2009-12-23 19:56:16 UTC (rev 449)
+++ trunk/OpenMPT/soundlib/Sndmix.cpp 2009-12-25 12:00:26 UTC (rev 450)
@@ -1227,18 +1227,17 @@
}
else if(IsCompatibleMode(TRK_FASTTRACKER2)) // FastTracker 2
{
- // Using MilkyTracker's logic - still not perfect
BYTE note = pChn->nNote;
int arpPos = 0;
if (!(m_dwSongFlags & SONG_FIRSTTICK))
{
- arpPos = ((int)m_nTickCount - (int)m_nMusicSpeed) % 3;
- if(arpPos < 0) arpPos += 3;
+ arpPos = ((int)m_nMusicSpeed - (int)m_nTickCount) % 3;
+ if((m_nMusicSpeed > 18) && (m_nMusicSpeed - m_nTickCount > 16)) arpPos = 2; // swedish tracker logic, I love it
switch(arpPos)
{
- case 1: note += (pChn->nArpeggio & 0x0F); break; // x/y are swapped!
- case 2: note += (pChn->nArpeggio >> 4); break;
+ case 1: note += (pChn->nArpeggio >> 4); break;
+ case 2: note += (pChn->nArpeggio & 0x0F); break;
}
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-02-05 18:18:00
|
Revision: 482
http://modplug.svn.sourceforge.net/modplug/?rev=482&view=rev
Author: saga-games
Date: 2010-02-05 18:17:51 +0000 (Fri, 05 Feb 2010)
Log Message:
-----------
[Imp] PSM Loader: Better handling of SC0 effect
[Imp] IT Saver: Compatibility export saves stereo samples again, as other tracker like Schism also support this.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/Load_psm.cpp
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2010-01-27 20:27:41 UTC (rev 481)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-02-05 18:17:51 UTC (rev 482)
@@ -2910,10 +2910,15 @@
if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80;
if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01;
UINT flags = RS_PCM8S;
+ if (psmp->uFlags & CHN_STEREO)
+ {
+ flags = RS_STPCM8S;
+ itss.flags |= 0x04;
+ }
if (psmp->uFlags & CHN_16BIT)
{
itss.flags |= 0x02;
- flags = RS_PCM16S;
+ flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S;
}
itss.samplepointer = dwPos;
if (!(psmp->pSample) || !(psmp->nLength))
Modified: trunk/OpenMPT/soundlib/Load_psm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_psm.cpp 2010-01-27 20:27:41 UTC (rev 481)
+++ trunk/OpenMPT/soundlib/Load_psm.cpp 2010-02-05 18:17:51 UTC (rev 482)
@@ -1131,7 +1131,17 @@
break;
case 0x2A: // note cut
command = CMD_S3MCMDEX;
- if(param == 0) param = 1;
+ if(param == 0) // in S3M mode, SC0 is ignored, so we convert it to a note cut.
+ {
+ if(row_data->note == NOTE_NONE)
+ {
+ row_data->note = NOTE_NOTECUT;
+ command = CMD_NONE;
+ } else
+ {
+ param = 1;
+ }
+ }
param |= 0xC0;
break;
case 0x2B: // note delay
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-02-14 15:03:04
|
Revision: 494
http://modplug.svn.sourceforge.net/modplug/?rev=494&view=rev
Author: saga-games
Date: 2010-02-14 15:02:53 +0000 (Sun, 14 Feb 2010)
Log Message:
-----------
[Fix] ITP / J2B loader: Sample slot limits were not checked properly.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/IT_DEFS.H
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/load_j2b.cpp
Modified: trunk/OpenMPT/soundlib/IT_DEFS.H
===================================================================
--- trunk/OpenMPT/soundlib/IT_DEFS.H 2010-02-14 00:22:40 UTC (rev 493)
+++ trunk/OpenMPT/soundlib/IT_DEFS.H 2010-02-14 15:02:53 UTC (rev 494)
@@ -140,7 +140,8 @@
extern BYTE autovibit2xm[8];
extern BYTE autovibxm2it[8];
-#define ITP_VERSION 0x00000102 // v1.02
+#define ITP_VERSION 0x00000102 // v1.02
+#define ITP_FILE_ID 0x2e697470 // .itp ASCII
enum IT_ReaderBitMasks {
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2010-02-14 00:22:40 UTC (rev 493)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-02-14 15:02:53 UTC (rev 494)
@@ -450,8 +450,7 @@
// Check file ID
memcpy(&id,lpStream+streamPos,sizeof(DWORD));
- if(id != 0x2e697470) return false; // .itp
- m_nType = MOD_TYPE_IT;
+ if(id != ITP_FILE_ID) return false;
streamPos += sizeof(DWORD);
memcpy(&id,lpStream+streamPos,sizeof(DWORD));
@@ -461,6 +460,8 @@
if(version > ITP_VERSION)
return false;
+ m_nType = MOD_TYPE_IT;
+
// Song name
// name string length
@@ -736,6 +737,9 @@
nsmp = id;
streamPos += sizeof(DWORD);
+ if(nsmp < 1 || nsmp >= MAX_SAMPLES)
+ return false;
+
// Sample struct
memcpy(&pis,lpStream+streamPos,sizeof(ITSAMPLESTRUCT));
streamPos += sizeof(ITSAMPLESTRUCT);
@@ -1554,7 +1558,7 @@
// File ID
- DWORD id = 0x2e697470; // .itp ASCII
+ DWORD id = ITP_FILE_ID;
fwrite(&id, 1, sizeof(id), f);
id = ITP_VERSION;
Modified: trunk/OpenMPT/soundlib/load_j2b.cpp
===================================================================
--- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-02-14 00:22:40 UTC (rev 493)
+++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-02-14 15:02:53 UTC (rev 494)
@@ -339,7 +339,7 @@
dwMemPos += sizeof(AMFFCHUNK_INSTRUMENT);
SAMPLEINDEX nSmp = inschunk->sample + 1;
- if(nSmp > MAX_SAMPLES)
+ if(nSmp >= MAX_SAMPLES)
break;
m_nSamples = max(m_nSamples, nSmp);
@@ -398,7 +398,7 @@
dwMemPos += dwHeadlen;
SAMPLEINDEX nSmp = instheadchunk->sample + 1;
- if(nSmp > MAX_SAMPLES)
+ if(nSmp >= MAX_SAMPLES)
break;
m_nSamples = max(m_nSamples, nSmp);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-03-20 17:26:39
|
Revision: 538
http://modplug.svn.sourceforge.net/modplug/?rev=538&view=rev
Author: saga-games
Date: 2010-03-20 17:26:29 +0000 (Sat, 20 Mar 2010)
Log Message:
-----------
[Ref] Moved the "visited rows" code a bit so that it can be used for other purposes later. It's also using bool vectors now, as those are apparently specialized to really only take up a bit per vector item.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndfile.h
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-03-20 12:32:15 UTC (rev 537)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-03-20 17:26:29 UTC (rev 538)
@@ -77,7 +77,9 @@
//-------------------------------------------
{
bool dummy = false;
- return GetLength(dummy, bAdjust, bTotal);
+ double result = GetLength(dummy, bAdjust, bTotal);
+ InitializeVisitedRows(true); // forget that we went over the whole module.
+ return result;
}
double CSoundFile::GetLength(bool& targetReached, BOOL bAdjust, BOOL bTotal, ORDERINDEX endOrder, ROWINDEX endRow)
@@ -117,31 +119,7 @@
nPattern = Order[0];
nRow = nNextRow = 0;
- /* Now, some fun code begins: This will determine if a specific row in a pattern (orderlist item)
- has been visited before. This way, we can tell when the module starts to loop, i.e. when we have determined
- the song length (or found out that a given point of the module cannot be reached).
- The concept is actually very simple: Store a boolean value for every row for every possible orderlist item.
- To save some memory, I have decided to actually store 8 row flags in one uint8 item, to save some
- space. Hence, there's some funky bit-shifting here and there.
- As the modplug engine already deals with pattern loops sufficiently, there's no problem with (infinite) pattern loops
- in this code. However, if you're going to use this idea somewhere else, bare in mind that rows inside pattern loops
- should only be evaluated once, or else the algorithm will cancel too early!
- */
- vector<vector<uint8> > visited_rows;
- visited_rows.resize(Order.GetLengthTailTrimmed());
- for(ORDERINDEX nOrd = 0; nOrd < Order.GetLengthTailTrimmed(); nOrd++)
- {
- PATTERNINDEX nPat = Order[nOrd];
- ROWINDEX nSize = 0;
- if(Patterns.IsValidPat(nPat))
- nSize = Patterns[nPat].GetNumRows();
- // as we need one vector unit per 8 rows, we will probably have to add some non-existing rows
- // (f.e. if a pattern has 7 rows, we actually need another row so it's 8 rows = 1 byte - got it? ;)
- if(nSize & 7)
- nSize += 8;
- nSize >>= 3; // 2^3 elements per vector unit!
- visited_rows[nOrd].resize(nSize, 0);
- }
+ InitializeVisitedRows(true);
for (;;)
{
@@ -187,16 +165,8 @@
break;
}
- // Detect backward loop (or more general: if this row has been visited before)
- size_t row_slot = nRow >> 3;
- uint8 row_mask = 1 << (nRow & 7);
- // This should always be true - but who knows what different parts of the program could modify the patterns and orders while this test is running?
- if(nCurrentPattern < visited_rows.size() && row_slot < visited_rows[nCurrentPattern].size())
- {
- if((visited_rows[nCurrentPattern][row_slot] & row_mask) != 0)
- break; // we visited this row already - this module must be looping.
- visited_rows[nCurrentPattern][row_slot] |= row_mask;
- }
+ if(IsRowVisited(nCurrentPattern, nRow, true))
+ break;
// Update next position
nNextRow = nRow + 1;
@@ -3594,7 +3564,7 @@
m_nMusicTempo = param;
}
// Tempo Slide
- else if (param < 0x20 && m_nTickCount) //rewbs.tempoSlideFix: only slide if (T0x or T1x) and tick is not 0
+ else if (param < 0x20 && !(m_dwSongFlags & SONG_FIRSTTICK)) //rewbs.tempoSlideFix: only slide if (T0x or T1x) and tick is not 0
{
if ((param & 0xF0) == 0x10)
m_nMusicTempo += (param & 0x0F); //rewbs.tempoSlideFix: no *2
@@ -3625,7 +3595,7 @@
{
//IT compatibility 10. Pattern loops (+ same fix for XM and MOD files)
if(IsCompatibleMode(TRK_IMPULSETRACKER | TRK_FASTTRACKER2 | TRK_PROTRACKER))
- pChn->nPatternLoop = m_nRow+1;
+ pChn->nPatternLoop = m_nRow + 1;
return -1;
}
@@ -4042,4 +4012,97 @@
pChn->nOldFinePortaUpDown = abs(tickParam);
pChn->m_CalculateFreq = true;
+}
+
+
+/* Now, some fun code begins: This will determine if a specific row in a pattern (orderlist item)
+ has been visited before. This way, we can tell when the module starts to loop, i.e. when we have determined
+ the song length (or found out that a given point of the module cannot be reached).
+ The concept is actually very simple: Store a boolean value for every row for every possible orderlist item.
+
+ Specific implementations:
+
+ Length detection code:
+ As the modplug engine already deals with pattern loops sufficiently, there's no problem with (infinite) pattern loops
+ in this code.
+
+ Normal player code:
+ Bare in mind that rows inside pattern loops should only be evaluated once, or else the algorithm will cancel too early!
+ So in that case, the pattern loop rows have to be reset when looping back.
+*/
+
+
+void CSoundFile::InitializeVisitedRows(const bool bReset)
+//-------------------------------------------------------
+{
+ m_bVisitedRows.resize(Order.GetLengthTailTrimmed());
+
+ for(ORDERINDEX nOrd = 0; nOrd < Order.GetLengthTailTrimmed(); nOrd++)
+ {
+ // If we want to reset the vectors completely, we overwrite exisiting items with 0.
+ if(bReset)
+ {
+ for(size_t i = 0; i < m_bVisitedRows[nOrd].size(); i++)
+ {
+ m_bVisitedRows[nOrd][i] = false;
+ }
+ }
+ m_bVisitedRows[nOrd].resize(GetVisitedRowsVectorSize(Order[nOrd]), false);
+ }
+}
+
+
+// (Un)sets a given row as visited.
+void CSoundFile::SetRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bVisited)
+//---------------------------------------------------------------------------------------------
+{
+ const ORDERINDEX nMaxOrd = Order.GetLengthTailTrimmed();
+ if(nOrd >= nMaxOrd)
+ return;
+
+ // The module might have been edited in the meantime - so we have to extend this a bit.
+ if(nOrd >= m_bVisitedRows.size() || nRow >= m_bVisitedRows[nOrd].size())
+ InitializeVisitedRows(false);
+
+ m_bVisitedRows[nOrd][nRow] = bVisited;
+}
+
+
+// Returns if a given row has been visited yet.
+// If bAutoSet is true, the queried row will automatically be marked as visited.
+// Use this parameter instead of consecutive IsRowVisited/SetRowVisited calls, as it's faster.
+bool CSoundFile::IsRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bAutoSet)
+//--------------------------------------------------------------------------------------------
+{
+ const ORDERINDEX nMaxOrd = Order.GetLengthTailTrimmed();
+ if(nOrd >= nMaxOrd)
+ return false;
+
+ // The row slot for this row has not been assigned yet - Just return false, as this means that the program has not played the row yet.
+ if(nOrd >= m_bVisitedRows.size() || nRow >= m_bVisitedRows[nOrd].size())
+ {
+ if(bAutoSet)
+ SetRowVisited(nOrd, nRow, true);
+ else
+ return false;
+ }
+
+ if(m_bVisitedRows[nOrd][nRow])
+ return true; // we visited this row already - this module must be looping.
+
+ if(bAutoSet)
+ m_bVisitedRows[nOrd][nRow] = true;
+
+ return false;
+}
+
+
+// Get the needed vector size for pattern nPat.
+size_t CSoundFile::GetVisitedRowsVectorSize(const PATTERNINDEX nPat)
+//------------------------------------------------------------------
+{
+ if(Patterns.IsValidPat(nPat))
+ return (size_t)(Patterns[nPat].GetNumRows());
+ else
+ return 0;
}
\ No newline at end of file
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2010-03-20 12:32:15 UTC (rev 537)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2010-03-20 17:26:29 UTC (rev 538)
@@ -532,8 +532,11 @@
uint16 m_ModFlags;
const CModSpecifications* m_pModSpecs;
+ // For handling backwards jumps and stuff to prevent infinite loops when counting the mod length or rendering to wav.
+ vector<vector<bool> > m_bVisitedRows;
+
public: // Static Members
static UINT m_nXBassDepth, m_nXBassRange;
static float m_nMaxSample;
@@ -578,7 +581,8 @@
m_nGlobalVolumeDestination, m_nSamplePreAmp, m_nVSTiVolume;
long m_lHighResRampingGlobalVolume;
UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide;
- LONG m_nMinPeriod, m_nMaxPeriod, m_nRepeatCount;
+ LONG m_nMinPeriod, m_nMaxPeriod;
+ LONG m_nRepeatCount; // -1 means repeat infinitely.
DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples;
UINT m_nMaxOrderPosition, m_nPatternNames;
LPSTR m_lpszSongComments, m_lpszPatternNames;
@@ -965,7 +969,15 @@
void BuildDefaultInstrument();
long GetSampleOffset();
+// A couple of functions for handling backwards jumps and stuff to prevent infinite loops when counting the mod length or rendering to wav.
public:
+ void InitializeVisitedRows(const bool bReset = true);
+private:
+ void SetRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bVisited = true);
+ bool IsRowVisited(const ORDERINDEX nOrd, const ROWINDEX nRow, const bool bAutoSet = true);
+ size_t GetVisitedRowsVectorSize(const PATTERNINDEX nPat);
+
+public:
// "importance" of every FX command. Table is used for importing from formats with multiple effect colums
// and is approximately the same as in SchismTracker.
static uint16 CSoundFile::GetEffectWeight(MODCOMMAND::COMMAND cmd);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-03-20 22:00:36
|
Revision: 539
http://modplug.svn.sourceforge.net/modplug/?rev=539&view=rev
Author: saga-games
Date: 2010-03-20 22:00:26 +0000 (Sat, 20 Mar 2010)
Log Message:
-----------
[Fix] XM compatibility: New instrument + tone portamento = ignore new instrument (fixes partytime.xm by cancer)
[Ref] Minor code cleanup.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndfile.h
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-03-20 17:26:29 UTC (rev 538)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-03-20 22:00:26 UTC (rev 539)
@@ -400,7 +400,8 @@
}
}
nSpeedCount += nMusicSpeed;
- switch(m_nTempoMode) {
+ switch(m_nTempoMode)
+ {
case tempo_mode_alternative:
dElapsedTime += 60000.0 / (1.65625 * (double)(nMusicSpeed * nMusicTempo)); break;
case tempo_mode_modern:
@@ -435,10 +436,10 @@
//////////////////////////////////////////////////////////////////////////////////////////////////
// Effects
-void CSoundFile::InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta, BOOL bUpdVol, BOOL bResetEnv)
+void CSoundFile::InstrumentChange(MODCHANNEL *pChn, UINT instr, bool bPorta, bool bUpdVol, bool bResetEnv)
//--------------------------------------------------------------------------------------------------------
{
- BOOL bInstrumentChanged = FALSE;
+ bool bInstrumentChanged = false;
if (instr >= MAX_INSTRUMENTS) return;
MODINSTRUMENT *pIns = Instruments[instr];
@@ -469,8 +470,8 @@
// bInstrumentChanged is used for IT carry-on env option
if (pIns != pChn->pModInstrument)
{
- bInstrumentChanged = TRUE;
- pChn->pModInstrument = pIns;
+ bInstrumentChanged = true;
+ // we will set the new instrument later.
}
else
{
@@ -483,6 +484,15 @@
returnAfterVolumeAdjust = true;
}
}
+
+ // XM compatibility: new instrument + portamento = forget it!
+ if(bInstrumentChanged && bPorta && IsCompatibleMode(TRK_FASTTRACKER2))
+ {
+ return;
+ } else
+ {
+ pChn->pModInstrument = pIns;
+ }
// Update Volume
if (bUpdVol)
@@ -1152,7 +1162,7 @@
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;
+ bool bPorta = ((cmd != CMD_TONEPORTAMENTO) && (cmd != CMD_TONEPORTAVOL) && (volcmd != VOLCMD_TONEPORTAMENTO)) ? false : true;
UINT nStartTick = 0;
@@ -1380,13 +1390,13 @@
if (instr)
{
MODSAMPLE *psmp = pChn->pModSample;
- InstrumentChange(pChn, instr, bPorta, TRUE);
+ InstrumentChange(pChn, instr, bPorta, true);
pChn->nNewIns = 0;
// Special IT case: portamento+note causes sample change -> ignore portamento
if ((m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_MPT))
&& (psmp != pChn->pModSample) && (note) && (note < 0x80))
{
- bPorta = FALSE;
+ bPorta = false;
}
}
// New Note ?
@@ -1394,7 +1404,7 @@
{
if ((!instr) && (pChn->nNewIns) && (note < 0x80))
{
- InstrumentChange(pChn, pChn->nNewIns, bPorta, FALSE, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? FALSE : TRUE);
+ InstrumentChange(pChn, pChn->nNewIns, bPorta, false, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? false : true);
pChn->nNewIns = 0;
}
NoteChange(nChn, note, bPorta, (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2)) ? false : true);
@@ -3330,7 +3340,7 @@
{
int vol = pChn->nVolume;
- // FT2 compatibility: Retrig + volume will not change volume of retrigged notes
+ // XM compatibility: Retrig + volume will not change volume of retrigged notes
if(!IsCompatibleMode(TRK_FASTTRACKER2) || !(pChn->nRowVolCmd == VOLCMD_VOLUME))
{
if (retrigTable1[dv])
@@ -3352,7 +3362,7 @@
{
if ((pChn->nRowInstr) && (param < 0x100))
{
- InstrumentChange(pChn, pChn->nRowInstr, FALSE, FALSE);
+ InstrumentChange(pChn, pChn->nRowInstr, false, false);
bResetEnv = true;
}
if (param < 0x100) bResetEnv = true;
@@ -3872,7 +3882,8 @@
UINT CSoundFile::GetBestPlugin(UINT nChn, UINT priority, bool respectMutes)
//-------------------------------------------------------------------------
{
- if (nChn > MAX_CHANNELS) { //Check valid channel number
+ if (nChn > MAX_CHANNELS) //Check valid channel number
+ {
return 0;
}
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2010-03-20 17:26:29 UTC (rev 538)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2010-03-20 22:00:26 UTC (rev 539)
@@ -821,7 +821,7 @@
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 InstrumentChange(MODCHANNEL *pChn, UINT instr, BOOL bPorta=FALSE,BOOL bUpdVol=TRUE,BOOL bResetEnv=TRUE);
+ void InstrumentChange(MODCHANNEL *pChn, UINT instr, bool bPorta = false, bool bUpdVol = true, bool bResetEnv = true);
// Channel Effects
void KeyOff(UINT nChn);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-03-21 17:25:20
|
Revision: 541
http://modplug.svn.sourceforge.net/modplug/?rev=541&view=rev
Author: saga-games
Date: 2010-03-21 17:25:13 +0000 (Sun, 21 Mar 2010)
Log Message:
-----------
[Fix] Threw out the old ULT loader in favor of Storlek's loader from SchismTracker (used with permission from the author himself). This is a lot more accurate than MPT's old loader.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_ult.cpp
trunk/OpenMPT/soundlib/Sndfile.cpp
trunk/OpenMPT/soundlib/Sndfile.h
Modified: trunk/OpenMPT/soundlib/Load_ult.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_ult.cpp 2010-03-21 14:45:39 UTC (rev 540)
+++ trunk/OpenMPT/soundlib/Load_ult.cpp 2010-03-21 17:25:13 UTC (rev 541)
@@ -1,227 +1,419 @@
/*
- * This source code is public domain.
+ * Purpose: Load ULT (UltraTracker) modules
+ * Authors: Storlek (Original author - http://schismtracker.org/)
+ * Johannes Schultz (OpenMPT Port, tweaks)
*
- * Copied to OpenMPT from libmodplug.
- *
- * Authors: Olivier Lapicque <oli...@jp...>
- *
-*/
+ * Thanks to Storlek for allowing me to use this code!
+ */
#include "stdafx.h"
#include "sndfile.h"
-#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
+enum
+{
+ ULT_16BIT = 4,
+ ULT_LOOP = 8,
+ ULT_PINGPONGLOOP = 16,
+};
-#define ULT_16BIT 0x04
-#define ULT_LOOP 0x08
-#define ULT_BIDI 0x10
-
#pragma pack(1)
+struct ULT_SAMPLE
+{
+ char name[32];
+ char filename[12];
+ uint32 loop_start;
+ uint32 loop_end;
+ uint32 size_start;
+ uint32 size_end;
+ uint8 volume; // 0-255, apparently prior to 1.4 this was logarithmic?
+ uint8 flags; // above
+ uint16 speed; // only exists for 1.4+
+ int16 finetune;
+};
+STATIC_ASSERT(sizeof(ULT_SAMPLE) >= 64);
+#pragma pack()
-// Raw ULT header struct:
-typedef struct tagULTHEADER
+#define ASSERT_CAN_READ(x) \
+ if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false;
+
+/* Unhandled effects:
+5x1 - do not loop sample (x is unused)
+5xC - end loop and finish sample
+9xx - set sample offset to xx * 1024
+ with 9yy: set sample offset to xxyy * 4
+E0x - set vibrato strength (2 is normal)
+F00 - reset speed/tempo to 6/125
+
+Apparently 3xx will CONTINUE to slide until it reaches its destination, or
+until a 300 effect is encountered. I'm not attempting to handle this (yet).
+
+The logarithmic volume scale used in older format versions here, or pretty
+much anywhere for that matter. I don't even think Ultra Tracker tries to
+convert them. */
+
+static const uint8 ult_efftrans[] =
{
- char id[15];
- char songtitle[32];
- BYTE reserved;
-} ULTHEADER;
+ CMD_ARPEGGIO,
+ CMD_PORTAMENTOUP,
+ CMD_PORTAMENTODOWN,
+ CMD_TONEPORTAMENTO,
+ CMD_VIBRATO,
+ CMD_NONE,
+ CMD_NONE,
+ CMD_TREMOLO,
+ CMD_NONE,
+ CMD_OFFSET,
+ CMD_VOLUMESLIDE,
+ CMD_PANNING8,
+ CMD_VOLUME,
+ CMD_PATTERNBREAK,
+ CMD_NONE, // extended effects, processed separately
+ CMD_SPEED,
+};
+static void TranslateULTCommands(uint8 *pe, uint8 *pp)
+//----------------------------------------------------
+{
+ uint8 e = *pe & 0x0F;
+ uint8 p = *pp;
-// Raw ULT sampleinfo struct:
-typedef struct tagULTSAMPLE
+ *pe = ult_efftrans[e];
+
+ switch (e)
+ {
+ case 0x00:
+ if (!p)
+ *pe = CMD_NONE;
+ break;
+ case 0x03:
+ // 300 apparently stops sliding, which is totally weird
+ if (!p)
+ p = 1; // close enough?
+ break;
+ case 0x05:
+ // play backwards
+ if((p & 0x0F) == 0x02)
+ {
+ *pe = CMD_S3MCMDEX;
+ p = 0x9F;
+ }
+ break;
+ case 0x0A:
+ // blah, this sucks
+ if (p & 0xF0)
+ p &= 0xF0;
+ break;
+ case 0x0B:
+ // mikmod does this wrong, resulting in values 0-225 instead of 0-255
+ p = (p & 0x0F) * 0x11;
+ break;
+ case 0x0C: // volume
+ p >>= 2;
+ break;
+ case 0x0D: // pattern break
+ p = 10 * (p >> 4) + (p & 0x0F);
+ case 0x0E: // special
+ switch (p >> 4)
+ {
+ case 0x01:
+ *pe = CMD_PORTAMENTOUP;
+ p = 0xF0 | (p & 0x0F);
+ break;
+ case 0x02:
+ *pe = CMD_PORTAMENTODOWN;
+ p = 0xF0 | (p & 0x0F);
+ break;
+ case 0x08:
+ *pe = CMD_S3MCMDEX;
+ p = 0x60 | (p & 0x0F);
+ break;
+ case 0x09:
+ *pe = CMD_RETRIG;
+ p &= 0x0F;
+ break;
+ case 0x0A:
+ *pe = CMD_VOLUMESLIDE;
+ p = ((p & 0x0F) << 4) | 0x0F;
+ break;
+ case 0x0B:
+ *pe = CMD_VOLUMESLIDE;
+ p = 0xF0 | (p & 0x0F);
+ break;
+ case 0x0C: case 0x0D:
+ *pe = CMD_S3MCMDEX;
+ break;
+ }
+ break;
+ case 0x0F:
+ if (p > 0x2F)
+ *pe = CMD_TEMPO;
+ break;
+ }
+
+ *pp = p;
+}
+
+static int ReadULTEvent(MODCOMMAND *note, const BYTE *lpStream, DWORD *dwMP, const DWORD dwMemLength)
+//---------------------------------------------------------------------------------------------------
{
- CHAR samplename[32];
- CHAR dosname[12];
- LONG loopstart;
- LONG loopend;
- LONG sizestart;
- LONG sizeend;
- BYTE volume;
- BYTE flags;
- WORD finetune;
-} ULTSAMPLE;
+ DWORD dwMemPos = *dwMP;
+ uint8 b, repeat = 1;
+ uint8 cmd1, cmd2; // 1 = vol col, 2 = fx col in the original schismtracker code
+ uint8 param1, param2;
-#pragma pack()
+ ASSERT_CAN_READ(1)
+ b = lpStream[dwMemPos++];
+ if (b == 0xFC) // repeat event
+ {
+ ASSERT_CAN_READ(2);
+ repeat = lpStream[dwMemPos++];
+ b = lpStream[dwMemPos++];
+ }
+ ASSERT_CAN_READ(4)
+ note->note = (b > 0 && b < 61) ? b + 36 : NOTE_NONE;
+ note->instr = lpStream[dwMemPos++];
+ b = lpStream[dwMemPos++];
+ cmd1 = b & 0x0F;
+ cmd2 = b >> 4;
+ param1 = lpStream[dwMemPos++];
+ param2 = lpStream[dwMemPos++];
+ TranslateULTCommands(&cmd1, ¶m1);
+ TranslateULTCommands(&cmd2, ¶m2);
+ // sample offset -- this is even more special than digitrakker's
+ if(cmd1 == CMD_OFFSET && cmd2 == CMD_OFFSET)
+ {
+ uint32 off = ((param1 << 8) | param2) >> 6;
+ cmd1 = CMD_NONE;
+ param1 = (uint8)min(off, 0xFF);
+ } else if(cmd1 == CMD_OFFSET)
+ {
+ uint32 off = param1 * 4;
+ param1 = (uint8)min(off, 0xFF);
+ } else if(cmd2 == CMD_OFFSET)
+ {
+ uint32 off = param2 * 4;
+ param2 = (uint8)min(off, 0xFF);
+ } else if(cmd1 == cmd2)
+ {
+ // don't try to figure out how ultratracker does this, it's quite random
+ cmd2 = CMD_NONE;
+ }
+ if (cmd2 == CMD_VOLUME || (cmd2 == CMD_NONE && cmd1 != CMD_VOLUME))
+ {
+ // swap commands
+ std::swap(cmd1, cmd2);
+ std::swap(param1, param2);
+ }
+ // Do that dance.
+ // Maybe I should quit rewriting this everywhere and make a generic version :P
+ int n;
+ for (n = 0; n < 4; n++)
+ {
+ if(CSoundFile::ConvertVolEffect(&cmd1, ¶m1, (n >> 1) ? true : false))
+ {
+ n = 5;
+ break;
+ }
+ std::swap(cmd1, cmd2);
+ std::swap(param1, param2);
+ }
+ if (n < 5)
+ {
+ if (CSoundFile::GetEffectWeight((MODCOMMAND::COMMAND)cmd1) > CSoundFile::GetEffectWeight((MODCOMMAND::COMMAND)cmd2))
+ {
+ std::swap(cmd1, cmd2);
+ std::swap(param1, param2);
+ }
+ cmd1 = CMD_NONE;
+ }
+ if (!cmd1)
+ param1 = 0;
+ if (!cmd2)
+ param2 = 0;
+
+ note->volcmd = cmd1;
+ note->vol = param1;
+ note->command = cmd2;
+ note->param = param2;
+
+ *dwMP = dwMemPos;
+ return repeat;
+}
+
bool CSoundFile::ReadUlt(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
- ULTHEADER *pmh = (ULTHEADER *)lpStream;
- ULTSAMPLE *pus;
- UINT nos, nop;
DWORD dwMemPos = 0;
+ uint8 ult_version;
- // try to read module header
- if ((!lpStream) || (dwMemLength < 0x100)) return false;
- if (strncmp(pmh->id,"MAS_UTrack_V00",14)) return false;
- // Warning! Not supported ULT format, trying anyway
- // if ((pmh->id[14] < '1') || (pmh->id[14] > '4')) return false;
+ // Tracker ID
+ ASSERT_CAN_READ(15);
+ if (memcmp(lpStream, "MAS_UTrack_V00", 14) != 0)
+ return false;
+ dwMemPos += 14;
+ ult_version = lpStream[dwMemPos++];
+ if (ult_version < '1' || ult_version > '4')
+ return false;
+ ult_version -= '0';
+
+ ASSERT_CAN_READ(32);
+ memcpy(m_szNames[0], lpStream + dwMemPos, 32);
+ SetNullTerminator(m_szNames[0]);
+ dwMemPos += 32;
+
m_nType = MOD_TYPE_ULT;
- m_nDefaultSpeed = 6;
- m_nDefaultTempo = 125;
- memcpy(m_szNames[0], pmh->songtitle, 31);
- SpaceToNullStringFixed(m_szNames[0], 31);
- // read songtext
- dwMemPos = sizeof(ULTHEADER);
- if ((pmh->reserved) && (dwMemPos + pmh->reserved * 32 < dwMemLength))
+ m_dwSongFlags = SONG_ITCOMPATMODE | SONG_ITOLDEFFECTS; // this will be converted to IT format by MPT.
+ SetModFlag(MSF_COMPATIBLE_PLAY, true);
+
+ ASSERT_CAN_READ(1);
+ uint8 nNumLines = (uint8)lpStream[dwMemPos++];
+ ASSERT_CAN_READ((DWORD)(nNumLines * 32));
+ // read "nNumLines" lines, each containing 32 characters.
+ if(m_lpszSongComments != nullptr)
+ delete(m_lpszSongComments);
+ m_lpszSongComments = new char[(nNumLines * 33) + 1];
+ if(m_lpszSongComments)
{
- UINT len = pmh->reserved * 32;
- m_lpszSongComments = new char[len + 1 + pmh->reserved];
- if (m_lpszSongComments)
+ for(size_t nLine = 0; nLine < nNumLines; nLine++)
{
- for (UINT l=0; l<pmh->reserved; l++)
- {
- memcpy(m_lpszSongComments+l*33, lpStream+dwMemPos+l*32, 32);
- m_lpszSongComments[l*33+32] = 0x0D;
- }
- m_lpszSongComments[len] = 0;
+ memcpy(m_lpszSongComments + nLine * 33, lpStream + dwMemPos + nLine * 32, 32);
+ m_lpszSongComments[nLine * 33 + 32] = 0x0D;
}
- dwMemPos += len;
+ m_lpszSongComments[nNumLines * 33] = 0;
}
- if (dwMemPos >= dwMemLength) return true;
- nos = lpStream[dwMemPos++];
- m_nSamples = nos;
- if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1;
- UINT smpsize = 64;
- if (pmh->id[14] >= '4') smpsize += 2;
- if (dwMemPos + nos*smpsize + 256 + 2 > dwMemLength) return true;
- for (UINT ins=1; ins<=nos; ins++, dwMemPos+=smpsize) if (ins<=m_nSamples)
+ dwMemPos += nNumLines * 32;
+
+ ASSERT_CAN_READ(1);
+ m_nSamples = (SAMPLEINDEX)lpStream[dwMemPos++];
+ if(m_nSamples >= MAX_SAMPLES)
+ return false;
+
+ for(SAMPLEINDEX nSmp = 0; nSmp < m_nSamples; nSmp++)
{
- pus = (ULTSAMPLE *)(lpStream+dwMemPos);
- MODSAMPLE *pSmp = &Samples[ins];
- memcpy(m_szNames[ins], pus->samplename, 31);
- memcpy(pSmp->filename, pus->dosname, 12);
- SpaceToNullStringFixed(m_szNames[ins], 31);
+ ULT_SAMPLE ultSmp;
+ MODSAMPLE *pSmp = &(Samples[nSmp + 1]);
+ // annoying: v4 added a field before the end of the struct
+ if(ult_version >= 4)
+ {
+ ASSERT_CAN_READ(sizeof(ULT_SAMPLE));
+ memcpy(&ultSmp, lpStream + dwMemPos, sizeof(ULT_SAMPLE));
+ dwMemPos += sizeof(ULT_SAMPLE);
+
+ ultSmp.speed = LittleEndianW(ultSmp.speed);
+ } else
+ {
+ ASSERT_CAN_READ(sizeof(64));
+ memcpy(&ultSmp, lpStream + dwMemPos, 64);
+ dwMemPos += 64;
+
+ ultSmp.finetune = ultSmp.speed;
+ ultSmp.speed = 8363;
+ }
+ ultSmp.finetune = LittleEndianW(ultSmp.finetune);
+ ultSmp.loop_start = LittleEndian(ultSmp.loop_start);
+ ultSmp.loop_end = LittleEndian(ultSmp.loop_end);
+ ultSmp.size_start = LittleEndian(ultSmp.size_start);
+ ultSmp.size_end = LittleEndian(ultSmp.size_end);
+
+ memcpy(m_szNames[nSmp + 1], ultSmp.name, 32);
+ SetNullTerminator(m_szNames[nSmp + 1]);
+ memcpy(pSmp->filename, ultSmp.filename, 12);
SpaceToNullStringFixed(pSmp->filename, 12);
- pSmp->nLoopStart = pus->loopstart;
- pSmp->nLoopEnd = pus->loopend;
- pSmp->nLength = pus->sizeend - pus->sizestart;
- pSmp->nVolume = pus->volume;
+
+ if(ultSmp.size_end <= ultSmp.size_start)
+ continue;
+ pSmp->nLength = ultSmp.size_end - ultSmp.size_start;
+ pSmp->nLoopStart = ultSmp.loop_start;
+ pSmp->nLoopEnd = min(ultSmp.loop_end, pSmp->nLength);
+ pSmp->nVolume = ultSmp.volume;
pSmp->nGlobalVol = 64;
- pSmp->nC5Speed = 8363;
- if (pmh->id[14] >= '4')
+
+ /* mikmod does some weird integer math here, but it didn't really work for me */
+ pSmp->nC5Speed = ultSmp.speed;
+ if(ultSmp.finetune)
{
- pSmp->nC5Speed = pus->finetune;
+ pSmp->nC5Speed = (UINT)(((double)pSmp->nC5Speed) * pow(2, (((double)ultSmp.finetune) / (12.0 * 32768))));
}
- if (pus->flags & ULT_LOOP) pSmp->uFlags |= CHN_LOOP;
- if (pus->flags & ULT_BIDI) pSmp->uFlags |= CHN_PINGPONGLOOP;
- if (pus->flags & ULT_16BIT)
+
+ if(ultSmp.flags & ULT_LOOP)
+ pSmp->uFlags |= CHN_LOOP;
+ if(ultSmp.flags & ULT_PINGPONGLOOP)
+ pSmp->uFlags |= CHN_PINGPONGLOOP;
+ if(ultSmp.flags & ULT_16BIT)
{
pSmp->uFlags |= CHN_16BIT;
pSmp->nLoopStart >>= 1;
pSmp->nLoopEnd >>= 1;
}
}
- Order.ReadAsByte(lpStream+dwMemPos, 256, dwMemLength-dwMemPos);
+
+ // ult just so happens to use 255 for its end mark, so there's no need to fiddle with this
+ Order.ReadAsByte(lpStream + dwMemPos, 256, dwMemLength - dwMemPos);
dwMemPos += 256;
- m_nChannels = lpStream[dwMemPos] + 1;
- nop = lpStream[dwMemPos+1] + 1;
- dwMemPos += 2;
- if (m_nChannels > 32) m_nChannels = 32;
- // Default channel settings
- for (UINT nSet=0; nSet<m_nChannels; nSet++)
+
+ ASSERT_CAN_READ(2);
+ m_nChannels = lpStream[dwMemPos++] + 1;
+ PATTERNINDEX nNumPats = lpStream[dwMemPos++] + 1;
+
+ if(m_nChannels > MAX_BASECHANNELS || nNumPats > MAX_PATTERNS)
+ return false;
+
+ if(ult_version >= 3)
{
- ChnSettings[nSet].nVolume = 64;
- ChnSettings[nSet].nPan = (nSet & 1) ? 0x40 : 0xC0;
- }
- // read pan position table for v1.5 and higher
- if(pmh->id[14]>='3')
- {
- if (dwMemPos + m_nChannels > dwMemLength) return true;
- for(UINT t=0; t<m_nChannels; t++)
+ ASSERT_CAN_READ(m_nChannels);
+ for(CHANNELINDEX nChn = 0; nChn < m_nChannels; nChn++)
{
- ChnSettings[t].nPan = (lpStream[dwMemPos++] << 4) + 8;
- if (ChnSettings[t].nPan > 256) ChnSettings[t].nPan = 256;
+ ChnSettings[nChn].nPan = ((lpStream[dwMemPos + nChn] & 0x0F) << 4) + 8;
}
- }
- // Allocating Patterns
- for (UINT nAllocPat=0; nAllocPat<nop; nAllocPat++)
+ dwMemPos += m_nChannels;
+ } else
{
- if (nAllocPat < MAX_PATTERNS)
+ for(CHANNELINDEX nChn = 0; nChn < m_nChannels; nChn++)
{
- Patterns.Insert(nAllocPat, 64);
+ ChnSettings[nChn].nPan = (nChn & 1) ? 192 : 64;
}
}
- // Reading Patterns
- for (UINT nChn=0; nChn<m_nChannels; nChn++)
+
+ for(PATTERNINDEX nPat = 0; nPat < nNumPats; nPat++)
{
- for (UINT nPat=0; nPat<nop; nPat++)
+ if(Patterns.Insert(nPat, 64))
+ return false;
+ }
+
+ for(CHANNELINDEX nChn = 0; nChn < m_nChannels; nChn++)
+ {
+ MODCOMMAND evnote;
+ MODCOMMAND *note;
+ int repeat;
+ evnote.Clear();
+
+ for(PATTERNINDEX nPat = 0; nPat < nNumPats; nPat++)
{
- MODCOMMAND *pat = NULL;
-
- if (nPat < MAX_PATTERNS)
+ note = Patterns[nPat] + nChn;
+ ROWINDEX nRow = 0;
+ while(nRow < 64)
{
- pat = Patterns[nPat];
- if (pat) pat += nChn;
- }
- UINT row = 0;
- while (row < 64)
- {
- if (dwMemPos + 6 > dwMemLength) return true;
- UINT rep = 1;
- UINT note = lpStream[dwMemPos++];
- if (note == 0xFC)
+ repeat = ReadULTEvent(&evnote, lpStream, &dwMemPos, dwMemLength);
+ if(repeat + nRow > 64)
+ repeat = 64 - nRow;
+ if(repeat == 0) break;
+ while (repeat--)
{
- rep = lpStream[dwMemPos];
- note = lpStream[dwMemPos+1];
- dwMemPos += 2;
+ *note = evnote;
+ note += m_nChannels;
+ nRow++;
}
- UINT instr = lpStream[dwMemPos++];
- UINT eff = lpStream[dwMemPos++];
- UINT dat1 = lpStream[dwMemPos++];
- UINT dat2 = lpStream[dwMemPos++];
- UINT cmd1 = eff & 0x0F;
- UINT cmd2 = eff >> 4;
- if (cmd1 == 0x0C) dat1 >>= 2; else
- if (cmd1 == 0x0B) { cmd1 = dat1 = 0; }
- if (cmd2 == 0x0C) dat2 >>= 2; else
- if (cmd2 == 0x0B) { cmd2 = dat2 = 0; }
- while ((rep != 0) && (row < 64))
- {
- if (pat)
- {
- pat->instr = instr;
- if (note) pat->note = note + 36;
- if (cmd1 | dat1)
- {
- if (cmd1 == 0x0C)
- {
- pat->volcmd = VOLCMD_VOLUME;
- pat->vol = dat1;
- } else
- {
- pat->command = cmd1;
- pat->param = dat1;
- ConvertModCommand(pat);
- }
- }
- if (cmd2 == 0x0C)
- {
- pat->volcmd = VOLCMD_VOLUME;
- pat->vol = dat2;
- } else
- if ((cmd2 | dat2) && (!pat->command))
- {
- pat->command = cmd2;
- pat->param = dat2;
- ConvertModCommand(pat);
- }
- pat += m_nChannels;
- }
- row++;
- rep--;
- }
}
}
}
- // Reading Instruments
- for (UINT smp=1; smp<=m_nSamples; smp++) if (Samples[smp].nLength)
+
+ for(SAMPLEINDEX nSmp = 0; nSmp < m_nSamples; nSmp++)
{
- if (dwMemPos >= dwMemLength) return true;
- UINT flags = (Samples[smp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S;
- dwMemPos += ReadSample(&Samples[smp], flags, (LPSTR)(lpStream+dwMemPos), dwMemLength - dwMemPos);
+ dwMemPos += ReadSample(&Samples[nSmp + 1], (Samples[nSmp + 1].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
}
return true;
}
+#undef ASSERT_CAN_READ
Modified: trunk/OpenMPT/soundlib/Sndfile.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-03-21 14:45:39 UTC (rev 540)
+++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-03-21 17:25:13 UTC (rev 541)
@@ -65,6 +65,7 @@
extern void ITUnpack8Bit(LPSTR pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
extern void ITUnpack16Bit(LPSTR pSample, DWORD dwLen, LPBYTE lpMemFile, DWORD dwMemLength, BOOL b215);
+extern BYTE ImpulseTrackerPortaVolCmd[16];
#define MAX_PACK_TABLES 3
@@ -3825,4 +3826,138 @@
case CMD_NONE:
default: return 0;
}
-}
\ No newline at end of file
+}
+
+// Try to convert a fx column command (*e) into a volume column command.
+// Returns true if successful.
+// Some commands can only be converted by losing some precision.
+// If moving the command into the volume column is more important than accuracy, use bForce = true.
+// (Code translated from SchismTracker and mainly supposed to be used with loaders ported from this tracker)
+bool CSoundFile::ConvertVolEffect(uint8 *e, uint8 *p, bool bForce)
+//----------------------------------------------------------------
+{
+ switch (*e)
+ {
+ case CMD_NONE:
+ return true;
+ case CMD_VOLUME:
+ *e = VOLCMD_VOLUME;
+ *p = min(*p, 64);
+ break;
+ case CMD_PORTAMENTOUP:
+ if (bForce)
+ *p = min(*p, 9);
+ else if (*p > 9)
+ return false;
+ *e = VOLCMD_PORTAUP;
+ break;
+ case CMD_PORTAMENTODOWN:
+ if (bForce)
+ *p = min(*p, 9);
+ else if (*p > 9)
+ return false;
+ *e = VOLCMD_PORTADOWN;
+ break;
+ case CMD_TONEPORTAMENTO:
+ if (*p >= 0xF0)
+ {
+ // hack for people who can't type F twice :)
+ *e = VOLCMD_TONEPORTAMENTO;
+ *p = 0xFF;
+ return true;
+ }
+ for (uint8 n = 0; n < 10; n++)
+ {
+ if (bForce
+ ? (*p <= ImpulseTrackerPortaVolCmd[n])
+ : (*p == ImpulseTrackerPortaVolCmd[n]))
+ {
+ *e = VOLCMD_TONEPORTAMENTO;
+ *p = n;
+ return true;
+ }
+ }
+ return false;
+ case CMD_VIBRATO:
+ if (bForce)
+ *p = min(*p, 9);
+ else if (*p > 9)
+ return false;
+ *e = VOLCMD_VIBRATODEPTH;
+ break;
+ case CMD_FINEVIBRATO:
+ if (bForce)
+ *p = 0;
+ else if (*p)
+ return false;
+ *e = VOLCMD_VIBRATODEPTH;
+ break;
+ case CMD_PANNING8:
+ *p = min(64, *p * 64 / 255);
+ *e = VOLCMD_PANNING;
+ break;
+ case CMD_VOLUMESLIDE:
+ if (*p == 0)
+ return false;
+ if ((*p & 0xF) == 0) // Dx0 / Cx
+ {
+ if (bForce)
+ *p = min(*p >> 4, 9);
+ else if ((*p >> 4) > 9)
+ return false;
+ else
+ *p >>= 4;
+ *e = VOLCMD_VOLSLIDEUP;
+ } else if ((*p & 0xF0) == 0) // D0x / Dx
+ {
+ if (bForce)
+ *p = min(*p, 9);
+ else if (*p > 9)
+ return false;
+ *e = VOLCMD_VOLSLIDEDOWN;
+ } else if ((*p & 0xF) == 0xF) // DxF / Ax
+ {
+ if (bForce)
+ *p = min(*p >> 4, 9);
+ else if ((*p >> 4) > 9)
+ return false;
+ else
+ *p >>= 4;
+ *e = VOLCMD_FINEVOLUP;
+ } else if ((*p & 0xf0) == 0xf0) // DFx / Bx
+ {
+ if (bForce)
+ *p = min(*p, 9);
+ else if ((*p & 0xF) > 9)
+ return false;
+ else
+ *p &= 0xF;
+ *e = VOLCMD_FINEVOLDOWN;
+ } else // ???
+ {
+ return false;
+ }
+ break;
+ case CMD_S3MCMDEX:
+ switch (*p >> 4)
+ {
+ case 8:
+ *e = VOLCMD_PANNING;
+ *p = ((*p & 0xf) << 2) + 2;
+ return true;
+ case 0: case 1: case 2: case 0xF:
+ if (bForce)
+ {
+ *e = *p = 0;
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+ default:
+ return false;
+ }
+ return true;
+}
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2010-03-21 14:45:39 UTC (rev 540)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2010-03-21 17:25:13 UTC (rev 541)
@@ -981,6 +981,8 @@
// "importance" of every FX command. Table is used for importing from formats with multiple effect colums
// and is approximately the same as in SchismTracker.
static uint16 CSoundFile::GetEffectWeight(MODCOMMAND::COMMAND cmd);
+ // try to convert a an effect into a volume column effect.
+ static bool ConvertVolEffect(uint8 *e, uint8 *p, bool bForce);
};
#pragma warning(default : 4324) //structure was padded due to __declspec(align())
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-04-07 17:23:38
|
Revision: 566
http://modplug.svn.sourceforge.net/modplug/?rev=566&view=rev
Author: saga-games
Date: 2010-04-07 17:23:25 +0000 (Wed, 07 Apr 2010)
Log Message:
-----------
[Reg] Cannot create S3M files with more than 100 patterns anymore, because...
[Fix] ... it was possible to create S3M files where the 256 parapointers were not enough. It was possible to crash MPT with 669 files with SCRM at position 0x2C because MPT would allow more than 256 parapointer table entries, although it only reserved 256*2 bytes for it.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_s3m.cpp
trunk/OpenMPT/soundlib/mod_specifications.h
Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-04-07 15:19:36 UTC (rev 565)
+++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-04-07 17:23:25 UTC (rev 566)
@@ -270,7 +270,7 @@
dwMemPos = 0x60;
m_nType = MOD_TYPE_S3M;
- memset(m_szNames,0,sizeof(m_szNames));
+ memset(m_szNames, 0, sizeof(m_szNames));
memcpy(m_szNames[0], psfh.name, 28);
SpaceToNullStringFixed(m_szNames[0], 28);
// Speed
@@ -326,12 +326,18 @@
patnum = npat = psfh.patnum;
if (patnum > MAX_PATTERNS) patnum = MAX_PATTERNS;
memset(ptr, 0, sizeof(ptr));
- if (nins+npat)
+
+ // this seems to be corrupted, the table can't really hold that many values.
+ if(nins + npat > 256)
+ return false;
+
+ if (nins + npat)
{
- memcpy(ptr, lpStream+dwMemPos, 2*(nins+npat));
- dwMemPos += 2*(nins+npat);
- const UINT nLoopEnd = min(256, nins+npat);
- for (UINT j = 0; j < nLoopEnd; ++j) {
+ memcpy(ptr, lpStream + dwMemPos, 2 * (nins + npat));
+ dwMemPos += 2 * (nins + npat);
+ const UINT nLoopEnd = min(256, nins + npat);
+ for(UINT j = 0; j < nLoopEnd; ++j)
+ {
ptr[j] = LittleEndianW(ptr[j]);
}
if (psfh.panning_present == 252)
Modified: trunk/OpenMPT/soundlib/mod_specifications.h
===================================================================
--- trunk/OpenMPT/soundlib/mod_specifications.h 2010-04-07 15:19:36 UTC (rev 565)
+++ trunk/OpenMPT/soundlib/mod_specifications.h 2010-04-07 17:23:25 UTC (rev 566)
@@ -295,7 +295,7 @@
true, //Has notecut.
false, //No noteoff.
false, //No notefade.
- 240, //Pattern max.
+ 99, //Pattern max.
255, //Order max.
1, //Channel min
32, //Channel max
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-05-13 19:12:36
|
Revision: 592
http://modplug.svn.sourceforge.net/modplug/?rev=592&view=rev
Author: saga-games
Date: 2010-05-13 19:12:29 +0000 (Thu, 13 May 2010)
Log Message:
-----------
[Imp] Mod Loaders: Instead of creating messageboxes in various places, errors are now written to the log.
[Imp] Binary files are now less often falsely recognized as early MOD files (15 samples without header): If the orderlist contains orderlist items > 128, loading is cancelled.
[Ref] Bits of refactoring here and there.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_gdm.cpp
trunk/OpenMPT/soundlib/Load_imf.cpp
trunk/OpenMPT/soundlib/Load_it.cpp
trunk/OpenMPT/soundlib/Load_mo3.cpp
trunk/OpenMPT/soundlib/Load_mod.cpp
trunk/OpenMPT/soundlib/Load_psm.cpp
trunk/OpenMPT/soundlib/Load_s3m.cpp
trunk/OpenMPT/soundlib/load_j2b.cpp
Modified: trunk/OpenMPT/soundlib/Load_gdm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -14,6 +14,9 @@
#include "stdafx.h"
#include "sndfile.h"
+#ifdef MODPLUG_TRACKER
+#include "../mptrack/moddoc.h"
+#endif // MODPLUG_TRACKER
#pragma pack(1)
@@ -255,9 +258,11 @@
if(Patterns.Insert(iPat, 64))
{
+#ifdef MODPLUG_TRACKER
CString s;
s.Format(TEXT("Allocating patterns failed starting from pattern %u"), iPat);
- MessageBox(NULL, s, TEXT("OpenMPT GDM import"), MB_ICONERROR);
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(s);
+#endif // MODPLUG_TRACKER
break;
}
Modified: trunk/OpenMPT/soundlib/Load_imf.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_imf.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_imf.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -8,6 +8,9 @@
#include "stdafx.h"
#include "sndfile.h"
+#ifdef MODPLUG_TRACKER
+#include "../mptrack/moddoc.h"
+#endif // MODPLUG_TRACKER
#pragma pack(1)
@@ -365,9 +368,11 @@
if(Patterns.Insert(nPat, nrows))
{
+#ifdef MODPLUG_TRACKER
CString s;
s.Format(TEXT("Allocating patterns failed starting from pattern %u"), nPat);
- MessageBox(NULL, s, TEXT("OpenMPT IMF import"), MB_ICONERROR);
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(s);
+#endif // MODPLUG_TRACKER
break;
}
row_data = Patterns[nPat];
Modified: trunk/OpenMPT/soundlib/Load_it.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_it.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -1354,9 +1354,11 @@
{
if(Patterns.Insert(npat, 64))
{
+#ifdef MODPLUG_TRACKER
CString s;
- s.Format("Allocating patterns failed starting from pattern %u", npat);
- MessageBox(NULL, s, "", MB_ICONERROR);
+ s.Format(TEXT("Allocating patterns failed starting from pattern %u"), npat);
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(s);
+#endif
break;
}
continue;
Modified: trunk/OpenMPT/soundlib/Load_mo3.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mo3.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_mo3.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -8,9 +8,10 @@
#include "stdafx.h"
#include "sndfile.h"
+#ifdef MODPLUG_TRACKER
+#include "../mptrack/moddoc.h"
+#endif // MODPLUG_TRACKER
-
-
// decode a MO3 file (returns the same "exit codes" as UNMO3.EXE, eg. 0=success)
// IN: data/len = MO3 data/len
// OUT: data/len = decoded data/len (if successful)
@@ -29,11 +30,14 @@
#ifdef NO_MO3_SUPPORT
/* As of August 2009, the format revision is 5; Versions > 31 are unlikely to exist in the next few years,
so we will just ignore those if there's no UNMO3 library to tell us if the file is valid or not
- (avoid messagebox with .MOD files that have a song name starting with "MO3" */
+ (avoid log entry with .MOD files that have a song name starting with "MO3" */
if(lpStream[3] > 31) return false;
- AfxMessageBox(GetStrI18N(__TEXT("The file appears to be a MO3 file, but this OpenMPT build does not support loading MO3 files.")));
+#ifdef MODPLUG_TRACKER
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(GetStrI18N(__TEXT("The file appears to be a MO3 file, but this OpenMPT build does not support loading MO3 files.")));
+#endif // MODPLUG_TRACKER
return false;
+
#else
bool b_result = false; // result of trying to load the module, false == fail.
@@ -44,7 +48,9 @@
HMODULE unmo3 = LoadLibrary(_TEXT("unmo3.dll"));
if(unmo3 == NULL) // Didn't succeed.
{
- AfxMessageBox(GetStrI18N(_TEXT("Loading MO3 file failed because unmo3.dll could not be loaded.")), MB_ICONINFORMATION);
+#ifdef MODPLUG_TRACKER
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(GetStrI18N(_TEXT("Loading MO3 file failed because unmo3.dll could not be loaded.")));
+#endif // MODPLUG_TRACKER
}
else //case: dll loaded succesfully.
{
Modified: trunk/OpenMPT/soundlib/Load_mod.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mod.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_mod.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -326,6 +326,10 @@
m_nChannels = 4;
bFLT8 = false;
}
+
+ // chances are very high that we're dealing with a non-MOD file here.
+ if(m_nSamples == 15 && i >= 0x80)
+ return false;
}
if(bFLT8)
Modified: trunk/OpenMPT/soundlib/Load_psm.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_psm.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_psm.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -20,6 +20,9 @@
#include "stdafx.h"
#include "sndfile.h"
+#ifdef MODPLUG_TRACKER
+#include "../mptrack/moddoc.h"
+#endif // MODPLUG_TRACKER
#pragma pack(1)
@@ -32,67 +35,68 @@
struct PSMNEWHEADER
{
- DWORD formatID; // "PSM " (new format)
- DWORD fileSize; // Filesize - 12
- DWORD fileInfoID; // "FILE" Start of file info
+ uint32 formatID; // "PSM " (new format)
+ uint32 fileSize; // Filesize - 12
+ uint32 fileInfoID; // "FILE" Start of file info
};
struct PSMSONGHEADER
{
- CHAR songType[9]; // Mostly "MAINSONG " (But not in Extreme Pinball!)
- BYTE compression; // 1 - uncompressed
- BYTE numChannels; // Number of channels, usually 4
+ char songType[9]; // Mostly "MAINSONG " (But not in Extreme Pinball!)
+ uint8 compression; // 1 - uncompressed
+ uint8 numChannels; // Number of channels, usually 4
};
struct PSMOLDSAMPLEHEADER // Regular sample header
{
- BYTE flags;
- CHAR fileName[8]; // Filename of the original module (without extension)
- DWORD sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal)
- CHAR sampleName[33];
- CHAR unknown1[6]; // 00 00 00 00 00 FF
- WORD sampleNumber;
- DWORD sampleLength;
- DWORD loopStart;
- DWORD loopEnd; // FF FF FF FF = end of sample
- BYTE unknown3;
- BYTE defaulPan; // unused?
- BYTE defaultVolume;
- DWORD unknown4;
- WORD C5Freq;
- CHAR unknown5[21]; // 00 ... 00
+ uint8 flags;
+ char fileName[8]; // Filename of the original module (without extension)
+ uint32 sampleID; // INS0...INS9 (only last digit of sample ID, i.e. sample 1 and sample 11 are equal)
+ char sampleName[33];
+ uint8 unknown1[6]; // 00 00 00 00 00 FF
+ uint16 sampleNumber;
+ uint32 sampleLength;
+ uint32 loopStart;
+ uint32 loopEnd; // FF FF FF FF = end of sample
+ uint8 unknown3;
+ uint8 defaulPan; // unused?
+ uint8 defaultVolume;
+ uint32 unknown4;
+ uint16 C5Freq;
+ uint8 unknown5[21]; // 00 ... 00
};
struct PSMNEWSAMPLEHEADER // Sinaria sample header (and possibly other games)
{
- BYTE flags;
- CHAR fileName[8]; // Filename of the original module (without extension)
- CHAR sampleID[8]; // INS0...INS99999
- CHAR sampleName[33];
- CHAR unknown1[6]; // 00 00 00 00 00 FF
- WORD sampleNumber;
- DWORD sampleLength;
- DWORD loopStart;
- DWORD loopEnd;
- WORD unknown3;
- BYTE defaultPan; // unused?
- BYTE defaultVolume;
- DWORD unknown4;
- WORD C5Freq;
- CHAR unknown5[16]; // 00 ... 00
+ uint8 flags;
+ char fileName[8]; // Filename of the original module (without extension)
+ char sampleID[8]; // INS0...INS99999
+ char sampleName[33];
+ uint8 unknown1[6]; // 00 00 00 00 00 FF
+ uint16 sampleNumber;
+ uint32 sampleLength;
+ uint32 loopStart;
+ uint32 loopEnd;
+ uint16 unknown3;
+ uint8 defaultPan; // unused?
+ uint8 defaultVolume;
+ uint32 unknown4;
+ uint16 C5Freq;
+ char unknown5[16]; // 00 ... 00
};
#pragma pack()
struct PSMSUBSONG // For internal use (pattern conversion)
{
- BYTE channelPanning[MAX_BASECHANNELS], channelVolume[MAX_BASECHANNELS];
- bool channelSurround[MAX_BASECHANNELS];
- BYTE defaultTempo, defaultSpeed;
- CHAR songName[10];
+ uint8 channelPanning[MAX_BASECHANNELS], channelVolume[MAX_BASECHANNELS];
+ bool channelSurround[MAX_BASECHANNELS];
+ uint8 defaultTempo, defaultSpeed;
+ char songName[10];
ORDERINDEX startOrder, endOrder, restartPos;
- PSMSUBSONG() {
+ PSMSUBSONG()
+ {
memset(channelPanning, 128, sizeof(channelPanning));
memset(channelVolume, 64, sizeof(channelVolume));
memset(channelSurround, false, sizeof(channelSurround));
@@ -144,9 +148,9 @@
// pattern offset and identifier
PATTERNINDEX numPatterns = 0; // used for setting up the orderlist - final pattern count
- vector<DWORD> patternOffsets; // pattern offsets (sorted as they occour in the file)
- vector<DWORD> patternIDs; // pattern IDs (sorted as they occour in the file)
- vector<DWORD> orderOffsets; // combine the upper two vectors to get the offsets for each order item
+ vector<uint32> patternOffsets; // pattern offsets (sorted as they occour in the file)
+ vector<uint32> patternIDs; // pattern IDs (sorted as they occour in the file)
+ vector<uint32> orderOffsets; // combine the upper two vectors to get the offsets for each order item
patternOffsets.clear();
patternIDs.clear();
orderOffsets.clear();
@@ -159,8 +163,8 @@
{
// Skip through the chunks
ASSERT_CAN_READ(8);
- DWORD chunkID = LittleEndian(*(DWORD *)(lpStream + dwMemPos));
- DWORD chunkSize = LittleEndian(*(DWORD *)(lpStream + dwMemPos + 4));
+ uint32 chunkID = LittleEndian(*(uint32 *)(lpStream + dwMemPos));
+ uint32 chunkSize = LittleEndian(*(uint32 *)(lpStream + dwMemPos + 4));
dwMemPos += 8;
ASSERT_CAN_READ(chunkSize);
@@ -177,7 +181,7 @@
break;
case 0x444F4250: // "PBOD" - Pattern data of a single pattern
- if(chunkSize < 8 || chunkSize != LittleEndian(*(DWORD *)(lpStream + dwMemPos))) return false; // same value twice
+ if(chunkSize < 8 || chunkSize != LittleEndian(*(uint32 *)(lpStream + dwMemPos))) return false; // same value twice
// Pattern ID (something like "P0 " or "P13 ", or "PATT0 " in Sinaria) follows
if(memcmp(lpStream + dwMemPos + 4, "P", 1)) return false;
@@ -210,8 +214,8 @@
// "Sub sub chunks"
while(dwChunkPos + 8 < dwMemPos + chunkSize)
{
- DWORD subChunkID = LittleEndian(*(DWORD *)(lpStream + dwChunkPos));
- DWORD subChunkSize = LittleEndian(*(DWORD *)(lpStream + dwChunkPos + 4));
+ uint32 subChunkID = LittleEndian(*(uint32 *)(lpStream + dwChunkPos));
+ uint32 subChunkSize = LittleEndian(*(uint32 *)(lpStream + dwChunkPos + 4));
dwChunkPos += 8;
switch(subChunkID)
@@ -220,7 +224,7 @@
if(subChunkSize != 6) break;
{
- CHAR cversion[7];
+ char cversion[7];
memcpy(cversion, lpStream + dwChunkPos, 6);
cversion[6] = 0;
int version = atoi(cversion);
@@ -239,7 +243,7 @@
// Now, the interesting part begins!
DWORD dwSettingsOffset = dwChunkPos + 2;
- WORD nChunkCount = 0, nFirstOrderChunk = (WORD)-1;
+ uint16 nChunkCount = 0, nFirstOrderChunk = uint16_max;
// "Sub sub sub chunks" (grrrr, silly format)
while(dwSettingsOffset - dwChunkPos + 1 < subChunkSize)
@@ -257,7 +261,7 @@
char patternID[4]; // temporary
memcpy(patternID, lpStream + dwSettingsOffset + 2 + (bNewFormat ? 3 : 0), 3);
patternID[3] = 0;
- DWORD nPattern = atoi(patternID);
+ uint32 nPattern = atoi(patternID);
// seek which pattern has this ID
for(uint32 i = 0; i < patternIDs.size(); i++)
@@ -278,13 +282,13 @@
}
}
// decide whether this is the first order chunk or not (for finding out the correct restart position)
- if(nFirstOrderChunk == (WORD)-1) nFirstOrderChunk = nChunkCount;
+ if(nFirstOrderChunk == uint16_max) nFirstOrderChunk = nChunkCount;
dwSettingsOffset += 5 + (bNewFormat ? 4 : 0);
break;
case 0x04: // Restart position
{
- WORD nRestartChunk = LittleEndian(*(WORD *)(lpStream + dwSettingsOffset + 1));
+ uint16 nRestartChunk = LittleEndian(*(uint16 *)(lpStream + dwSettingsOffset + 1));
ORDERINDEX nRestartPosition = 0;
if(nRestartChunk >= nFirstOrderChunk) nRestartPosition = (ORDERINDEX)(nRestartChunk - nFirstOrderChunk);
subsong.restartPos += nRestartPosition;
@@ -359,9 +363,11 @@
break;
default: // How the hell should this happen? I've listened through almost all existing (original) PSM files. :)
+#ifdef MODPLUG_TRACKER
CString s;
s.Format("Report to the OpenMPT team: Unknown chunk %d found at position %d (in the OPLH chunk of this PSM file)", lpStream[dwSettingsOffset], dwSettingsOffset);
- MessageBox(NULL, s, TEXT("OpenMPT PSM import"), MB_ICONERROR);
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(s);
+#endif // MODPLUG_TRACKER
// anyway, in such cases, we have to quit as we don't know how big the chunk really is.
return false;
break;
@@ -377,7 +383,7 @@
case 0x4E415050: // PPAN - Channel panning table (used in Sinaria)
if(subChunkSize & 1) return false;
- for(DWORD i = 0; i < subChunkSize; i += 2)
+ for(uint32 i = 0; i < subChunkSize; i += 2)
{
CHANNELINDEX nChn = (CHANNELINDEX)(i >> 1);
if(nChn >= m_nChannels) break;
@@ -507,16 +513,18 @@
for(ORDERINDEX nOrd = 0; nOrd < Order.size(); nOrd++)
{
if(orderOffsets[nOrd] == nullptr) continue;
- DWORD dwPatternOffset = orderOffsets[nOrd];
+ uint32 dwPatternOffset = orderOffsets[nOrd];
if(dwPatternOffset + 2 > dwMemLength) return false;
- WORD patternSize = LittleEndianW(*(WORD *)(lpStream + dwPatternOffset));
+ uint16 patternSize = LittleEndianW(*(uint16 *)(lpStream + dwPatternOffset));
dwPatternOffset += 2;
if(Patterns.Insert(nPat, patternSize))
{
+#ifdef MODPLUG_TRACKER
CString s;
s.Format(TEXT("Allocating patterns failed starting from pattern %u"), nPat);
- MessageBox(NULL, s, TEXT("OpenMPT PSM import"), MB_ICONERROR);
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(s);
+#endif // MODPLUG_TRACKER
break;
}
@@ -527,9 +535,9 @@
for(int nRow = 0; nRow < patternSize; nRow++)
{
if(dwPatternOffset + 2 > dwMemLength) return false;
- WORD rowSize = LittleEndianW(*(WORD *)(lpStream + dwPatternOffset));
+ uint16 rowSize = LittleEndianW(*(uint16 *)(lpStream + dwPatternOffset));
- DWORD dwRowOffset = dwPatternOffset + 2;
+ uint32 dwRowOffset = dwPatternOffset + 2;
while(dwRowOffset < dwPatternOffset + rowSize)
{
@@ -579,7 +587,7 @@
{
// Effect present - convert
if(dwRowOffset + 2 > dwMemLength) return false;
- BYTE command = lpStream[dwRowOffset], param = lpStream[dwRowOffset + 1];
+ uint8 command = lpStream[dwRowOffset], param = lpStream[dwRowOffset + 1];
switch(command)
{
@@ -812,51 +820,51 @@
struct PSM16HEADER
{
- DWORD formatID; // "PSM\xFE" (PSM16)
- CHAR songName[59]; // Song title, padded with nulls
- BYTE lineEnd; // $1A
- BYTE songType; // Song Type bitfield
- BYTE formatVersion; // $10
- BYTE patternVersion; // 0 or 1
- BYTE songSpeed; //
- BYTE songTempo; // 32 ... 255
- BYTE masterVolume; // 0 ... 255
- WORD songLength; // 0 ... 255 (number of patterns to play in the song)
- WORD songOrders; // 0 ... 255 (same as previous value as no subsongs are present)
- WORD numPatterns; // 1 ... 255
- WORD numSamples; // 1 ... 255
- WORD numChannelsPlay; // 0 ... 32 (max. number of channels to play)
- WORD numChannelsReal; // 0 ... 32 (max. number of channels to process)
- DWORD orderOffset;
- DWORD panOffset;
- DWORD patOffset;
- DWORD smpOffset;
- DWORD commentsOffset;
- DWORD patSize; // Size of all patterns
- CHAR filler[40];
+ uint32 formatID; // "PSM\xFE" (PSM16)
+ char songName[59]; // Song title, padded with nulls
+ uint8 lineEnd; // $1A
+ uint8 songType; // Song Type bitfield
+ uint8 formatVersion; // $10
+ uint8 patternVersion; // 0 or 1
+ uint8 songSpeed; //
+ uint8 songTempo; // 32 ... 255
+ uint8 masterVolume; // 0 ... 255
+ uint16 songLength; // 0 ... 255 (number of patterns to play in the song)
+ uint16 songOrders; // 0 ... 255 (same as previous value as no subsongs are present)
+ uint16 numPatterns; // 1 ... 255
+ uint16 numSamples; // 1 ... 255
+ uint16 numChannelsPlay; // 0 ... 32 (max. number of channels to play)
+ uint16 numChannelsReal; // 0 ... 32 (max. number of channels to process)
+ uint32 orderOffset;
+ uint32 panOffset;
+ uint32 patOffset;
+ uint32 smpOffset;
+ uint32 commentsOffset;
+ uint32 patSize; // Size of all patterns
+ uint8 filler[40];
};
struct PSM16SMPHEADER
{
- CHAR filename[13]; // null-terminated
- CHAR name[24]; // dito
- DWORD offset; // in file
- DWORD memoffset; // not used
- WORD sampleNumber; // 1 ... 255
- BYTE flags; // sample flag bitfield
- DWORD length; // in bytes
- DWORD loopStart; // in samples?
- DWORD loopEnd; // in samples?
- CHAR finetune; // 0 ... 15 (useless? also, why is this almost always 70?)
- BYTE volume; // default volume
- WORD c2freq;
+ uint8 filename[13]; // null-terminated
+ uint8 name[24]; // dito
+ uint32 offset; // in file
+ uint32 memoffset; // not used
+ uint16 sampleNumber;// 1 ... 255
+ uint8 flags; // sample flag bitfield
+ uint32 length; // in bytes
+ uint32 loopStart; // in samples?
+ uint32 loopEnd; // in samples?
+ int8 finetune; // 0 ... 15 (useless? also, why is this almost always 70?)
+ uint8 volume; // default volume
+ uint16 c2freq;
};
struct PSM16PATHEADER
{
- WORD size; // includes header bytes
- BYTE numRows; // 1 ... 64
- BYTE numChans; // 1 ... 31
+ uint16 size; // includes header bytes
+ uint8 numRows; // 1 ... 64
+ uint8 numChans; // 1 ... 31
};
#pragma pack()
@@ -898,7 +906,7 @@
// Read orders
dwMemPos = LittleEndian(shdr->orderOffset);
ASSERT_CAN_READ((DWORD)LittleEndianW(shdr->songOrders) + 2);
- if(LittleEndian(shdr->orderOffset) > 4 && LittleEndian(*(DWORD *)(lpStream + dwMemPos - 4)) == 0x44524f50) // PORD
+ if(LittleEndian(shdr->orderOffset) > 4 && LittleEndian(*(uint32 *)(lpStream + dwMemPos - 4)) == 0x44524f50) // PORD
{
Order.ReadAsByte(lpStream + dwMemPos, LittleEndianW(shdr->songOrders), dwMemLength - dwMemPos);
}
@@ -906,7 +914,7 @@
// Read pan positions
dwMemPos = LittleEndian(shdr->panOffset);
ASSERT_CAN_READ(32);
- if(LittleEndian(shdr->panOffset) > 4 && LittleEndian(*(DWORD *)(lpStream + dwMemPos - 4)) == 0x4E415050) // PPAN
+ if(LittleEndian(shdr->panOffset) > 4 && LittleEndian(*(uint32 *)(lpStream + dwMemPos - 4)) == 0x4E415050) // PPAN
{
for(CHANNELINDEX i = 0; i < 32; i++)
{
@@ -919,7 +927,7 @@
// Read samples
dwMemPos = LittleEndian(shdr->smpOffset);
ASSERT_CAN_READ(0);
- if(LittleEndian(shdr->smpOffset) > 4 && LittleEndian(*(DWORD *)(lpStream + dwMemPos - 4)) == 0x48415350) // PSAH
+ if(LittleEndian(shdr->smpOffset) > 4 && LittleEndian(*(uint32 *)(lpStream + dwMemPos - 4)) == 0x48415350) // PSAH
{
SAMPLEINDEX iSmpCount = 0;
m_nSamples = LittleEndianW(shdr->numSamples);
@@ -1000,9 +1008,11 @@
if(Patterns.Insert(nPat, phdr->numRows))
{
+#ifdef MODPLUG_TRACKER
CString s;
s.Format(TEXT("Allocating patterns failed starting from pattern %u"), nPat);
- MessageBox(NULL, s, TEXT("OpenMPT PSM16 import"), MB_ICONERROR);
+ if(m_pModDoc != nullptr) m_pModDoc->AddToLog(s);
+#endif // MODPLUG_TRACKER
break;
}
Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -10,9 +10,11 @@
#include "stdafx.h"
#include "sndfile.h"
-#include "../mptrack/moddoc.h"
#include "../mptrack/misc_util.h"
#include "../mptrack/version.h"
+#ifdef MODPLUG_TRACKER
+#include "../mptrack/moddoc.h"
+#endif // MODPLUG_TRACKER
#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data"
@@ -218,9 +220,9 @@
bool CSoundFile::ReadS3M(const BYTE *lpStream, DWORD dwMemLength)
//---------------------------------------------------------------
{
- if ((!lpStream) || (dwMemLength <= sizeof(S3MFILEHEADER)+64)) return false;
+ if ((!lpStream) || (dwMemLength <= sizeof(S3MFILEHEADER) + 64)) return false;
- UINT insnum,patnum,nins,npat;
+ UINT insnum, patnum, nins, npat;
DWORD insfile[128];
WORD ptr[256];
BYTE s[1024];
@@ -512,11 +514,11 @@
if (psfh.flags & 0x10) m_dwSongFlags |= SONG_AMIGALIMITS;
#ifdef MODPLUG_TRACKER
- if(bHasAdlibPatches)
+ if(bHasAdlibPatches && m_pModDoc != nullptr)
{
- ::MessageBox(0, "This track uses Adlib instruments, which are not supported by OpenMPT.", "OpenMPT S3M Import", MB_OK|MB_ICONEXCLAMATION);
+ m_pModDoc->AddToLog("This track uses Adlib instruments, which are not supported by OpenMPT.");
}
-#endif
+#endif // MODPLUG_TRACKER
return true;
}
Modified: trunk/OpenMPT/soundlib/load_j2b.cpp
===================================================================
--- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-05-09 22:04:33 UTC (rev 591)
+++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-05-13 19:12:29 UTC (rev 592)
@@ -9,7 +9,9 @@
#include "stdafx.h"
#include "sndfile.h"
+#ifndef ZLIB_WINAPI
#define ZLIB_WINAPI
+#endif // ZLIB_WINAPI
#include "../zlib/zlib.h"
#pragma pack(1)
@@ -18,7 +20,7 @@
struct J2BHEADER
{
uint32 signature; // MUSE
- uint32 deadbeaf; // 0xDEADBEAF (AM) or 0xDEADBABE (AMFF)
+ uint32 deadbeaf; // 0xDEADBEAF (AM) or 0xDEADBABE (AMFF)
uint32 j2blength; // complete filesize
uint32 crc32; // checksum of the compressed data block
uint32 packed_length; // length of the compressed data block
@@ -80,7 +82,7 @@
{
uint32 signature; // "SAMP"
uint32 chunksize; // header + sample size
- uint32 headsize; // header size
+ uint32 headsize; // header size
char name[32];
uint16 pan;
uint16 volume;
@@ -485,6 +487,8 @@
// header is valid, now unpack the RIFF AM file using inflate
DWORD destSize = LittleEndian(header->unpacked_length);
Bytef *bOutput = new Bytef[destSize];
+ if(bOutput == nullptr)
+ return false;
int nRetVal = uncompress(bOutput, &destSize, &lpStream[dwMemPos], LittleEndian(header->packed_length));
bool bResult = false;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-05-15 20:27:02
|
Revision: 597
http://modplug.svn.sourceforge.net/modplug/?rev=597&view=rev
Author: saga-games
Date: 2010-05-15 20:26:56 +0000 (Sat, 15 May 2010)
Log Message:
-----------
[Ref] J2B Loader: Removed AM pattern loader from CSoundFile.
[Imp] J2B Loader: Added some security checks for possible malicious files where the patterns could be the first chunks, so that m_nChannels is not set yet.
[Imp] MOD/XM Loader: Don't load effect 37 as DelayCut anymore, since we cannot save it in MOD/XM files anyway...
[Ref] A bit more refactoring.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Load_mod.cpp
trunk/OpenMPT/soundlib/Sndfile.cpp
trunk/OpenMPT/soundlib/Sndfile.h
trunk/OpenMPT/soundlib/load_j2b.cpp
Modified: trunk/OpenMPT/soundlib/Load_mod.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Load_mod.cpp 2010-05-14 16:37:15 UTC (rev 596)
+++ trunk/OpenMPT/soundlib/Load_mod.cpp 2010-05-15 20:26:56 UTC (rev 597)
@@ -56,7 +56,7 @@
case 'Y' - 55: command = CMD_PANBRELLO; break; //34
case 'Z' - 55: command = CMD_MIDI; break; //35
case '\\' - 56: command = CMD_SMOOTHMIDI; break; //rewbs.smoothVST: 36
- case ':' - 21: command = CMD_DELAYCUT; break; //37
+ //case ':' - 21: command = CMD_DELAYCUT; break; //37
case '#' + 3: command = CMD_XPARAM; break; //rewbs.XMfixes - XParam is 38
default: command = 0;
}
@@ -450,7 +450,6 @@
#ifndef MODPLUG_NO_FILESAVE
-#pragma warning(disable:4100)
bool CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking, const bool bCompatibilityExport)
//-------------------------------------------------------------------------------------------
@@ -581,8 +580,10 @@
} //end for all patterns
//Check for unsaved patterns
- for (UINT ipat=nbp; ipat<MAX_PATTERNS; ipat++) {
- if (Patterns[ipat]) {
+ for (UINT ipat=nbp; ipat<MAX_PATTERNS; ipat++)
+ {
+ if (Patterns[ipat])
+ {
AfxMessageBox("Warning: this track contains at least 1 pattern after the highest pattern number referred to in the sequence.\r\nSuch patterns will not be saved in the .mod format.");
break;
}
@@ -620,5 +621,4 @@
return true;
}
-#pragma warning(default:4100)
#endif // MODPLUG_NO_FILESAVE
Modified: trunk/OpenMPT/soundlib/Sndfile.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-05-14 16:37:15 UTC (rev 596)
+++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-05-15 20:26:56 UTC (rev 597)
@@ -3134,14 +3134,15 @@
return *p;
}
-/* Try to write an (volume) effect in a given channel or any channel of a pattern in a specific row.
+
+/* Try to write an (volume column) effect in a given channel or any channel of a pattern in a specific row.
Usage: nPat - Pattern that should be modified
nRow - Row that should be modified
nEffect - (Volume) Effect that should be written
nParam - Effect that should be written
- bIsVolumeEffect - Indicates whether the given effect is a volume effect or not
+ bIsVolumeEffect - Indicates whether the given effect is a volume column effect or not
nChn - Channel that should be modified - use CHANNELINDEX_INVALID to allow all channels of the given row
- bAllowMultipleEffects - If false, No effect will be written if an effect of the same type is already present in the channel(s)
+ bAllowMultipleEffects - If false, No effect will be written if an effect of the same type is already present in the channel(s). Useful for f.e. tempo effects.
bAllowNextRow - Indicates whether it is allowed to use the next row if there's no space for the effect
bRetry - For internal use only. Indicates whether an effect "rewrite" has already taken place (for recursive calls)
*/
@@ -3160,7 +3161,7 @@
}
// Scan channel(s) for same effect type - if an effect of the same type is already present, exit.
- if(bAllowMultipleEffects == false)
+ if(!bAllowMultipleEffects)
{
for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++)
{
@@ -3191,7 +3192,8 @@
}
// Ok, apparently there's no space. If we haven't tried already, try to map it to the volume column or effect column instead.
- if(bRetry == true) {
+ if(bRetry)
+ {
// Move some effects that also work in the volume column, so there's place for our new effect.
if(!bIsVolumeEffect)
{
@@ -3285,22 +3287,24 @@
}
+// Set up channel panning and volume suitable for MOD + similar files. If the current mod type is not MOD, bForceSetup has to be set to true.
void CSoundFile::SetupMODPanning(bool bForceSetup)
//------------------------------------------------
{
// Setup LRRL panning, max channel volume
if((m_nType & MOD_TYPE_MOD) == 0 && bForceSetup == false) return;
- for (CHANNELINDEX nChn = 0; nChn < MAX_BASECHANNELS; nChn++)
+ for(CHANNELINDEX nChn = 0; nChn < MAX_BASECHANNELS; nChn++)
{
ChnSettings[nChn].nVolume = 64;
- if (gdwSoundSetup & SNDMIX_MAXDEFAULTPAN)
+ if(gdwSoundSetup & SNDMIX_MAXDEFAULTPAN)
ChnSettings[nChn].nPan = (((nChn & 3) == 1) || ((nChn & 3) == 2)) ? 256 : 0;
else
ChnSettings[nChn].nPan = (((nChn & 3) == 1) || ((nChn & 3) == 2)) ? 0xC0 : 0x40;
}
}
+
// Convert an Exx command (MOD) to Sxx command (S3M)
void CSoundFile::MODExx2S3MSxx(MODCOMMAND *m)
//-------------------------------------------
@@ -3323,6 +3327,7 @@
}
}
+
// Convert an Sxx command (S3M) to Exx command (MOD)
void CSoundFile::S3MSxx2MODExx(MODCOMMAND *m)
//-------------------------------------------
@@ -3345,6 +3350,7 @@
}
}
+
// Convert a mod command from one format to another.
void CSoundFile::ConvertCommand(MODCOMMAND *m, MODTYPE nOldType, MODTYPE nNewType)
//--------------------------------------------------------------------------------
@@ -3545,7 +3551,7 @@
///////////////////////
// Convert IT to S3M
- else if (oldTypeIsIT_MPT && newTypeIsS3M)
+ else if(oldTypeIsIT_MPT && newTypeIsS3M)
{
if(m->note == NOTE_KEYOFF || m->note == NOTE_FADE)
m->note = NOTE_NOTECUT;
@@ -3631,68 +3637,68 @@
if(m->command) switch(m->command)
{
- case CMD_RETRIG: // MOD only has E9x
- m->command = CMD_MODCMDEX;
- m->param = 0x90 | (m->param & 0x0F);
- break;
- case CMD_MODCMDEX: // This would turn into "Invert Loop", so let's better remove it
- if((m->param & 0xF0) == 0xF0) m->command = CMD_NONE;
- break;
+ case CMD_RETRIG: // MOD only has E9x
+ m->command = CMD_MODCMDEX;
+ m->param = 0x90 | (m->param & 0x0F);
+ break;
+ case CMD_MODCMDEX: // This would turn into "Invert Loop", so let's better remove it
+ if((m->param & 0xF0) == 0xF0) m->command = CMD_NONE;
+ break;
}
else switch(m->volcmd)
{
- case VOLCMD_VOLUME:
- m->command = CMD_VOLUME;
- m->param = m->vol;
- break;
- case VOLCMD_PANNING:
- m->command = CMD_PANNING8;
- m->param = CLAMP(m->vol << 2, 0, 0xFF);
- break;
- case VOLCMD_VOLSLIDEDOWN:
- m->command = CMD_VOLUMESLIDE;
- m->param = m->vol;
- break;
- case VOLCMD_VOLSLIDEUP:
- m->command = CMD_VOLUMESLIDE;
- m->param = m->vol << 4;
- break;
- case VOLCMD_FINEVOLDOWN:
- m->command = CMD_MODCMDEX;
- m->param = 0xB0 | m->vol;
- break;
- case VOLCMD_FINEVOLUP:
- m->command = CMD_MODCMDEX;
- m->param = 0xA0 | m->vol;
- break;
- case VOLCMD_PORTADOWN:
- m->command = CMD_PORTAMENTODOWN;
- m->param = m->vol << 2;
- break;
- case VOLCMD_PORTAUP:
- m->command = CMD_PORTAMENTOUP;
- m->param = m->vol << 2;
- break;
- case VOLCMD_TONEPORTAMENTO:
- m->command = CMD_TONEPORTAMENTO;
- m->param = m->vol << 2;
- break;
- case VOLCMD_VIBRATODEPTH:
- m->command = CMD_VIBRATO;
- m->param = m->vol;
- break;
- case VOLCMD_VIBRATOSPEED:
- m->command = CMD_VIBRATO;
- m->param = m->vol << 4;
- break;
- // OpenMPT-specific commands
- case VOLCMD_OFFSET:
- m->command = CMD_OFFSET;
- m->param = m->vol << 3;
- break;
- default:
- break;
+ case VOLCMD_VOLUME:
+ m->command = CMD_VOLUME;
+ m->param = m->vol;
+ break;
+ case VOLCMD_PANNING:
+ m->command = CMD_PANNING8;
+ m->param = CLAMP(m->vol << 2, 0, 0xFF);
+ break;
+ case VOLCMD_VOLSLIDEDOWN:
+ m->command = CMD_VOLUMESLIDE;
+ m->param = m->vol;
+ break;
+ case VOLCMD_VOLSLIDEUP:
+ m->command = CMD_VOLUMESLIDE;
+ m->param = m->vol << 4;
+ break;
+ case VOLCMD_FINEVOLDOWN:
+ m->command = CMD_MODCMDEX;
+ m->param = 0xB0 | m->vol;
+ break;
+ case VOLCMD_FINEVOLUP:
+ m->command = CMD_MODCMDEX;
+ m->param = 0xA0 | m->vol;
+ break;
+ case VOLCMD_PORTADOWN:
+ m->command = CMD_PORTAMENTODOWN;
+ m->param = m->vol << 2;
+ break;
+ case VOLCMD_PORTAUP:
+ m->command = CMD_PORTAMENTOUP;
+ m->param = m->vol << 2;
+ break;
+ case VOLCMD_TONEPORTAMENTO:
+ m->command = CMD_TONEPORTAMENTO;
+ m->param = m->vol << 2;
+ break;
+ case VOLCMD_VIBRATODEPTH:
+ m->command = CMD_VIBRATO;
+ m->param = m->vol;
+ break;
+ case VOLCMD_VIBRATOSPEED:
+ m->command = CMD_VIBRATO;
+ m->param = m->vol << 4;
+ break;
+ // OpenMPT-specific commands
+ case VOLCMD_OFFSET:
+ m->command = CMD_OFFSET;
+ m->param = m->vol << 3;
+ break;
+ default:
+ break;
}
m->volcmd = CMD_NONE;
} // End if (newTypeIsMOD)
@@ -3703,69 +3709,69 @@
{
if(!m->command) switch(m->volcmd)
{
- case VOLCMD_VOLSLIDEDOWN:
- m->command = CMD_VOLUMESLIDE;
- m->param = m->vol;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_VOLSLIDEUP:
- m->command = CMD_VOLUMESLIDE;
- m->param = m->vol << 4;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_FINEVOLDOWN:
- m->command = CMD_VOLUMESLIDE;
- m->param = 0xF0 | m->vol;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_FINEVOLUP:
- m->command = CMD_VOLUMESLIDE;
- m->param = (m->vol << 4) | 0x0F;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_PORTADOWN:
- m->command = CMD_PORTAMENTODOWN;
- m->param = m->vol << 2;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_PORTAUP:
- m->command = CMD_PORTAMENTOUP;
- m->param = m->vol << 2;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_TONEPORTAMENTO:
- m->command = CMD_TONEPORTAMENTO;
- m->param = m->vol << 2;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_VIBRATODEPTH:
- m->command = CMD_VIBRATO;
- m->param = m->vol;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_VIBRATOSPEED:
- m->command = CMD_VIBRATO;
- m->param = m->vol << 4;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_PANSLIDELEFT:
- m->command = CMD_PANNINGSLIDE;
- m->param = m->vol << 4;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_PANSLIDERIGHT:
- m->command = CMD_PANNINGSLIDE;
- m->param = m->vol;
- m->volcmd = CMD_NONE;
- break;
- // OpenMPT-specific commands
- case VOLCMD_OFFSET:
- m->command = CMD_OFFSET;
- m->param = m->vol << 3;
- m->volcmd = CMD_NONE;
- break;
- default:
- break;
+ case VOLCMD_VOLSLIDEDOWN:
+ m->command = CMD_VOLUMESLIDE;
+ m->param = m->vol;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_VOLSLIDEUP:
+ m->command = CMD_VOLUMESLIDE;
+ m->param = m->vol << 4;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_FINEVOLDOWN:
+ m->command = CMD_VOLUMESLIDE;
+ m->param = 0xF0 | m->vol;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_FINEVOLUP:
+ m->command = CMD_VOLUMESLIDE;
+ m->param = (m->vol << 4) | 0x0F;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_PORTADOWN:
+ m->command = CMD_PORTAMENTODOWN;
+ m->param = m->vol << 2;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_PORTAUP:
+ m->command = CMD_PORTAMENTOUP;
+ m->param = m->vol << 2;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_TONEPORTAMENTO:
+ m->command = CMD_TONEPORTAMENTO;
+ m->param = m->vol << 2;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_VIBRATODEPTH:
+ m->command = CMD_VIBRATO;
+ m->param = m->vol;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_VIBRATOSPEED:
+ m->command = CMD_VIBRATO;
+ m->param = m->vol << 4;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_PANSLIDELEFT:
+ m->command = CMD_PANNINGSLIDE;
+ m->param = m->vol << 4;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_PANSLIDERIGHT:
+ m->command = CMD_PANNINGSLIDE;
+ m->param = m->vol;
+ m->volcmd = CMD_NONE;
+ break;
+ // OpenMPT-specific commands
+ case VOLCMD_OFFSET:
+ m->command = CMD_OFFSET;
+ m->param = m->vol << 3;
+ m->volcmd = CMD_NONE;
+ break;
+ default:
+ break;
}
} // End if (newTypeIsS3M)
@@ -3775,24 +3781,24 @@
{
if(!m->command) switch(m->volcmd)
{
- case VOLCMD_PORTADOWN:
- m->command = CMD_PORTAMENTODOWN;
- m->param = m->vol << 2;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_PORTAUP:
- m->command = CMD_PORTAMENTOUP;
- m->param = m->vol << 2;
- m->volcmd = CMD_NONE;
- break;
- // OpenMPT-specific commands
- case VOLCMD_OFFSET:
- m->command = CMD_OFFSET;
- m->param = m->vol << 3;
- m->volcmd = CMD_NONE;
- break;
- default:
- break;
+ case VOLCMD_PORTADOWN:
+ m->command = CMD_PORTAMENTODOWN;
+ m->param = m->vol << 2;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_PORTAUP:
+ m->command = CMD_PORTAMENTOUP;
+ m->param = m->vol << 2;
+ m->volcmd = CMD_NONE;
+ break;
+ // OpenMPT-specific commands
+ case VOLCMD_OFFSET:
+ m->command = CMD_OFFSET;
+ m->param = m->vol << 3;
+ m->volcmd = CMD_NONE;
+ break;
+ default:
+ break;
}
} // End if (newTypeIsXM)
@@ -3802,35 +3808,35 @@
{
if(!m->command) switch(m->volcmd)
{
- case VOLCMD_VOLSLIDEDOWN:
- case VOLCMD_VOLSLIDEUP:
- case VOLCMD_FINEVOLDOWN:
- case VOLCMD_FINEVOLUP:
- case VOLCMD_PORTADOWN:
- case VOLCMD_PORTAUP:
- case VOLCMD_TONEPORTAMENTO:
- case VOLCMD_VIBRATODEPTH:
- // OpenMPT-specific commands
- case VOLCMD_OFFSET:
- m->vol = min(m->vol, 9);
- break;
- case VOLCMD_PANSLIDELEFT:
- m->command = CMD_PANNINGSLIDE;
- m->param = m->vol << 4;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_PANSLIDERIGHT:
- m->command = CMD_PANNINGSLIDE;
- m->param = m->vol;
- m->volcmd = CMD_NONE;
- break;
- case VOLCMD_VIBRATOSPEED:
- m->command = CMD_VIBRATO;
- m->param = m->vol << 4;
- m->volcmd = CMD_NONE;
- break;
- default:
- break;
+ case VOLCMD_VOLSLIDEDOWN:
+ case VOLCMD_VOLSLIDEUP:
+ case VOLCMD_FINEVOLDOWN:
+ case VOLCMD_FINEVOLUP:
+ case VOLCMD_PORTADOWN:
+ case VOLCMD_PORTAUP:
+ case VOLCMD_TONEPORTAMENTO:
+ case VOLCMD_VIBRATODEPTH:
+ // OpenMPT-specific commands
+ case VOLCMD_OFFSET:
+ m->vol = min(m->vol, 9);
+ break;
+ case VOLCMD_PANSLIDELEFT:
+ m->command = CMD_PANNINGSLIDE;
+ m->param = m->vol << 4;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_PANSLIDERIGHT:
+ m->command = CMD_PANNINGSLIDE;
+ m->param = m->vol;
+ m->volcmd = CMD_NONE;
+ break;
+ case VOLCMD_VIBRATOSPEED:
+ m->command = CMD_VIBRATO;
+ m->param = m->vol << 4;
+ m->volcmd = CMD_NONE;
+ break;
+ default:
+ break;
}
} // End if (newTypeIsIT)
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2010-05-14 16:37:15 UTC (rev 596)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2010-05-15 20:26:56 UTC (rev 597)
@@ -719,9 +719,6 @@
bool ReadJ2B(const LPCBYTE lpStream, const DWORD dwMemLength);
bool ReadMID(LPCBYTE lpStream, DWORD dwMemLength);
- void SetupMODPanning(bool bForceSetup = false); // Setup LRRL panning, max channel volume
- bool Convert_RIFF_AM_Pattern(PATTERNINDEX nPat, const LPCBYTE lpStream, DWORD dwMemLength, bool bIsAM); // used by ReadAM(...) to convert AM(FF) patterns
-
// Save Functions
#ifndef MODPLUG_NO_FILESAVE
UINT WriteSample(FILE *f, MODSAMPLE *pSmp, UINT nFlags, UINT nMaxLen=0);
@@ -754,6 +751,7 @@
static void ConvertCommand(MODCOMMAND *m, MODTYPE nOldType, MODTYPE nNewType); // Convert a complete MODCOMMAND item from one format to another
static void MODExx2S3MSxx(MODCOMMAND *m); // Convert Exx to Sxx
static void S3MSxx2MODExx(MODCOMMAND *m); // Convert Sxx to Exx
+ void SetupMODPanning(bool bForceSetup = false); // Setup LRRL panning, max channel volume
public:
// Real-time sound functions
Modified: trunk/OpenMPT/soundlib/load_j2b.cpp
===================================================================
--- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-05-14 16:37:15 UTC (rev 596)
+++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-05-15 20:26:56 UTC (rev 597)
@@ -1,6 +1,8 @@
/*
+ * load_j2b.cpp
+ * ------------
* Purpose: Load RIFF AM and RIFF AMFF modules (Galaxy Sound System).
- * Note: J2B is a compressed variant of RIFF AM and RIFF AMFF files used in Jazz Jackrabbit 2.
+ * Notes : J2B is a compressed variant of RIFF AM and RIFF AMFF files used in Jazz Jackrabbit 2.
* It seems like no other game used the AM(FF) format.
* Authors: Johannes Schultz (OpenMPT port)
* Chris Moeller (foo_dumb - this is almost a complete port of his code, thanks)
@@ -107,8 +109,8 @@
CMD_TREMOR, CMD_XFINEPORTAUPDOWN,
};
-bool CSoundFile::Convert_RIFF_AM_Pattern(PATTERNINDEX nPat, const LPCBYTE lpStream, DWORD dwMemLength, bool bIsAM)
-//----------------------------------------------------------------------------------------------------------------
+bool Convert_RIFF_AM_Pattern(PATTERNINDEX nPat, const LPCBYTE lpStream, DWORD dwMemLength, bool bIsAM, CSoundFile *pSndFile)
+//--------------------------------------------------------------------------------------------------------------------------
{
// version false = AMFF, true = AM
#define ASSERT_CAN_READ(x) \
@@ -120,12 +122,16 @@
ROWINDEX nRows = lpStream[0] + 1;
- if(Patterns.Insert(nPat, nRows))
+ if(pSndFile == nullptr || pSndFile->Patterns.Insert(nPat, nRows))
return false;
dwMemPos++;
- MODCOMMAND *mrow = Patterns[nPat];
+ const CHANNELINDEX nChannels = pSndFile->GetNumChannels();
+ if(nChannels == 0)
+ return false;
+
+ MODCOMMAND *mrow = pSndFile->Patterns[nPat];
MODCOMMAND *m = mrow;
ROWINDEX nRow = 0;
uint8 flags;
@@ -138,11 +144,11 @@
if (flags == 0)
{
nRow++;
- m = mrow = Patterns[nPat] + nRow * m_nChannels;
+ m = mrow = pSndFile->Patterns[nPat] + nRow * nChannels;
continue;
}
- m = mrow + min((flags & 0x1F), m_nChannels - 1);
+ m = mrow + min((flags & 0x1F), nChannels - 1);
if(flags & 0xE0)
{
@@ -179,7 +185,7 @@
m->param = ((m->param >> 4) * 10) + (m->param & 0x0F);
break;
case CMD_MODCMDEX:
- MODExx2S3MSxx(m);
+ pSndFile->MODExx2S3MSxx(m);
break;
case CMD_TEMPO:
if(m->param <= 0x1F) m->command = CMD_SPEED;
@@ -205,7 +211,7 @@
wsprintf(s, "J2B: Unknown command: 0x%X, param 0x%X", m->command, m->param);
Log(s);
}
-#endif
+#endif // DEBUG
m->command = CMD_NONE;
}
}
@@ -263,6 +269,7 @@
else if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) == 0x20204D41) bIsAM = true; // "AM "
else return false;
dwMemPos += 4;
+ m_nChannels = 0;
// go through all chunks now
while(dwMemPos < dwMemLength)
@@ -330,7 +337,7 @@
case 0x54544150: // "PATT" - Pattern data for one pattern
ASSERT_CAN_READ_CHUNK(5);
- Convert_RIFF_AM_Pattern(lpStream[dwMemPos], (LPCBYTE)(lpStream + dwMemPos + 5), LittleEndian(*(DWORD *)(lpStream + dwMemPos + 1)), bIsAM);
+ Convert_RIFF_AM_Pattern(lpStream[dwMemPos], (LPCBYTE)(lpStream + dwMemPos + 5), LittleEndian(*(DWORD *)(lpStream + dwMemPos + 1)), bIsAM, this);
break;
case 0x54534E49: // "INST" - Instrument (only in RIFF AMFF)
@@ -365,16 +372,17 @@
Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend);
Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate);
- if(LittleEndianW(smpchunk->flags) & 0x04)
+ uint16 flags = LittleEndianW(smpchunk->flags);
+ if(flags & 0x04)
Samples[nSmp].uFlags |= CHN_16BIT;
- if(LittleEndianW(smpchunk->flags) & 0x08)
+ if(flags & 0x08)
Samples[nSmp].uFlags |= CHN_LOOP;
- if(LittleEndianW(smpchunk->flags) & 0x10)
+ if(flags & 0x10)
Samples[nSmp].uFlags |= CHN_PINGPONGLOOP;
- if(LittleEndianW(smpchunk->flags) & 0x20)
+ if(flags & 0x20)
Samples[nSmp].uFlags |= CHN_PANNING;
- dwMemPos += ReadSample(&Samples[nSmp], (LittleEndianW(smpchunk->flags) & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
+ dwMemPos += ReadSample(&Samples[nSmp], (flags & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
}
break;
@@ -436,24 +444,26 @@
Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend);
Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate);
- if(LittleEndianW(smpchunk->flags) & 0x04)
+ uint16 flags = LittleEndianW(smpchunk->flags);
+ if(flags & 0x04)
Samples[nSmp].uFlags |= CHN_16BIT;
- if(LittleEndianW(smpchunk->flags) & 0x08)
+ if(flags & 0x08)
Samples[nSmp].uFlags |= CHN_LOOP;
- if(LittleEndianW(smpchunk->flags) & 0x10)
+ if(flags & 0x10)
Samples[nSmp].uFlags |= CHN_PINGPONGLOOP;
- if(LittleEndianW(smpchunk->flags) & 0x20)
+ if(flags & 0x20)
Samples[nSmp].uFlags |= CHN_PANNING;
dwMemPos += LittleEndian(smpchunk->headsize) + 12; // doesn't include the 3 first DWORDs
- dwMemPos += ReadSample(&Samples[nSmp], (LittleEndianW(smpchunk->flags) & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
+ dwMemPos += ReadSample(&Samples[nSmp], (flags & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos);
}
break;
}
dwMemPos = dwChunkEnd;
- // RIFF AM has a padding byte
- if(bIsAM && (LittleEndian(chunkheader->chunksize) & 1)) dwMemPos++;
+ // RIFF AM has a padding byte so that all chunks have an even size.
+ if(bIsAM && (LittleEndian(chunkheader->chunksize) & 1))
+ dwMemPos++;
}
return true;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <sag...@us...> - 2010-06-06 16:33:15
|
Revision: 618
http://modplug.svn.sourceforge.net/modplug/?rev=618&view=rev
Author: saga-games
Date: 2010-06-06 16:33:09 +0000 (Sun, 06 Jun 2010)
Log Message:
-----------
[Fix] XM Compatibility: Various fixes to the pattern loop command (E6x), including a crucial FT2 bug: When E60 is used on a pattern row x, the following pattern also starts from row x instead of the beginning of the pattern, unless there was a Dxx or Cxx effect.
Modified Paths:
--------------
trunk/OpenMPT/soundlib/Snd_fx.cpp
trunk/OpenMPT/soundlib/Sndfile.cpp
trunk/OpenMPT/soundlib/Sndfile.h
trunk/OpenMPT/soundlib/Sndmix.cpp
Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-06 12:40:17 UTC (rev 617)
+++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-06 16:33:09 UTC (rev 618)
@@ -236,16 +236,20 @@
patternBreakOnThisRow=true;
//Try to check next row for XPARAM
nextRow = nullptr;
- if (nRow < Patterns[nPattern].GetNumRows()-1) {
+ if (nRow < Patterns[nPattern].GetNumRows() - 1)
+ {
nextRow = Patterns[nPattern] + (nRow+1) * m_nChannels + nChn;
}
- if (nextRow && nextRow->command == CMD_XPARAM) {
+ if (nextRow && nextRow->command == CMD_XPARAM)
+ {
nNextRow = (param<<8) + nextRow->param;
- } else {
+ } else
+ {
nNextRow = param;
}
- if (!positionJumpOnThisRow) {
+ if (!positionJumpOnThisRow)
+ {
nNextPattern = nCurrentPattern + 1;
}
if (bAdjust)
@@ -1912,6 +1916,7 @@
// Position Jump
case CMD_POSITIONJUMP:
+ m_nNextPatStartRow = 0; // FT2 E60 bug
nPosJump = param;
if((m_dwSongFlags & SONG_PATTERNLOOP && m_nSeqOverride == 0))
{
@@ -1927,6 +1932,7 @@
// Pattern Break
case CMD_PATTERNBREAK:
+ m_nNextPatStartRow = 0; // FT2 E60 bug
m = NULL;
if (m_nRow < Patterns[m_nPattern].GetNumRows()-1)
{
@@ -1990,7 +1996,7 @@
// Pattern Break / Position Jump only if no loop running
if ((nBreakRow >= 0) || (nPosJump >= 0))
{
- BOOL bNoLoop = FALSE;
+ bool bNoLoop = false;
if (nPosJump < 0) nPosJump = m_nCurrentPattern+1;
if (nBreakRow < 0) nBreakRow = 0;
@@ -2011,7 +2017,7 @@
if (gdwSoundSetup & SNDMIX_NOBACKWARDJUMPS)
#endif
// Backward jump disabled
- bNoLoop = TRUE;
+ bNoLoop = true;
}
}
}
@@ -2032,7 +2038,7 @@
}
m_nNextPattern = nPosJump;
m_nNextRow = (UINT)nBreakRow;
- m_bPatternTransitionOccurred=true;
+ m_bPatternTransitionOccurred = true;
}
} //Ends condition (nBreakRow >= 0) || (nPosJump >= 0)
}
@@ -3640,8 +3646,8 @@
pChn->nPatternLoopCount--;
if(!pChn->nPatternLoopCount)
{
- //IT compatibility 10. Pattern loops (+ same fix for XM and MOD files)
- if(IsCompatibleMode(TRK_IMPULSETRACKER | TRK_FASTTRACKER2 | TRK_PROTRACKER))
+ //IT compatibility 10. Pattern loops (+ same fix for MOD files)
+ if(IsCompatibleMode(TRK_IMPULSETRACKER | TRK_PROTRACKER))
pChn->nPatternLoop = m_nRow + 1;
return -1;
@@ -3661,6 +3667,7 @@
}
pChn->nPatternLoopCount = param;
}
+ m_nNextPatStartRow = pChn->nPatternLoop; // Nasty FT2 E60 bug emulation!
return pChn->nPatternLoop;
} else
{
@@ -3990,12 +3997,12 @@
return nPlugin;
}
-UINT CSoundFile::GetBestMidiChan(MODCHANNEL *pChn) {
-//--------------------------------------------------
- if (pChn && pChn->pModInstrument) {
- if (pChn->pModInstrument->nMidiChannel) {
- return (pChn->pModInstrument->nMidiChannel-1)&0x0F;
- }
+UINT CSoundFile::GetBestMidiChan(MODCHANNEL *pChn)
+//------------------------------------------------
+{
+ if (pChn && pChn->pModInstrument && pChn->pModInstrument->nMidiChannel)
+ {
+ return (pChn->pModInstrument->nMidiChannel - 1) & 0x0F;
}
return 0;
}
@@ -4003,11 +4010,13 @@
void CSoundFile::HandlePatternTransitionEvents()
//----------------------------------------------
{
- if (m_bPatternTransitionOccurred) {
+ if (m_bPatternTransitionOccurred)
+ {
// MPT sequence override
if ((m_nSeqOverride > 0) && (m_nSeqOverride <= Order.size()))
{
- if (m_dwSongFlags & SONG_PATTERNLOOP) {
+ if (m_dwSongFlags & SONG_PATTERNLOOP)
+ {
m_nPattern = Order[m_nSeqOverride-1];
}
m_nNextPattern = m_nSeqOverride - 1;
@@ -4015,7 +4024,8 @@
}
// Channel mutes
- for (UINT chan=0; chan<m_nChannels; chan++) {
+ for (UINT chan=0; chan<m_nChannels; chan++)
+ {
if (m_bChannelMuteTogglePending[chan])
{
if(m_pModDoc)
@@ -4023,8 +4033,6 @@
m_bChannelMuteTogglePending[chan]=false;
}
}
-
-
m_bPatternTransitionOccurred=false;
}
Modified: trunk/OpenMPT/soundlib/Sndfile.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-06-06 12:40:17 UTC (rev 617)
+++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-06-06 16:33:09 UTC (rev 618)
@@ -539,6 +539,7 @@
m_nPattern = 0;
m_nCurrentPattern = 0;
m_nNextPattern = 0;
+ m_nNextPatStartRow = 0;
m_nSeqOverride = 0;
m_nRestartPos = 0;
m_nMinPeriod = 16;
@@ -1226,6 +1227,7 @@
m_nBufferCount = 0;
m_nPatternDelay = 0;
m_nFrameDelay = 0;
+ m_nNextPatStartRow = 0;
//m_nSeqOverride = 0;
}
@@ -1272,6 +1274,7 @@
m_nTotalCount = 0;
m_nPatternDelay = 0;
m_nFrameDelay = 0;
+ m_nNextPatStartRow = 0;
}
//m_dwSongFlags &= ~(SONG_PATTERNLOOP|SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
m_dwSongFlags &= ~(SONG_CPUVERYHIGH|SONG_FADINGSONG|SONG_ENDREACHED|SONG_GLOBALFADE);
@@ -1381,6 +1384,7 @@
m_nPatternDelay = 0;
m_nFrameDelay = 0;
m_nBufferCount = 0;
+ m_nNextPatStartRow = 0;
m_dwSongFlags |= SONG_PATTERNLOOP;
// m_nSeqOverride = 0;
}
@@ -1397,6 +1401,7 @@
m_nPatternDelay = 0;
m_nFrameDelay = 0;
m_nBufferCount = 0;
+ m_nNextPatStartRow = 0;
m_dwSongFlags &= ~SONG_PATTERNLOOP;
//m_nSeqOverride = 0;
}
Modified: trunk/OpenMPT/soundlib/Sndfile.h
===================================================================
--- trunk/OpenMPT/soundlib/Sndfile.h 2010-06-06 12:40:17 UTC (rev 617)
+++ trunk/OpenMPT/soundlib/Sndfile.h 2010-06-06 16:33:09 UTC (rev 618)
@@ -566,6 +566,7 @@
BYTE m_nMixLevels;
UINT m_nMusicSpeed, m_nMusicTempo;
ROWINDEX m_nNextRow, m_nRow;
+ ROWINDEX m_nNextPatStartRow; // for FT2's E60 bug
PATTERNINDEX m_nPattern;
ORDERINDEX m_nCurrentPattern, m_nNextPattern, m_nRestartPos, m_nSeqOverride;
//NOTE: m_nCurrentPattern and m_nNextPattern refer to order index - not pattern index.
Modified: trunk/OpenMPT/soundlib/Sndmix.cpp
===================================================================
--- trunk/OpenMPT/soundlib/Sndmix.cpp 2010-06-06 12:40:17 UTC (rev 617)
+++ trunk/OpenMPT/soundlib/Sndmix.cpp 2010-06-06 16:33:09 UTC (rev 618)
@@ -625,7 +625,7 @@
BOOL CSoundFile::ProcessRow()
//---------------------------
{
- if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay)
+ if (++m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay + 1) + m_nFrameDelay)
{
HandlePatternTransitionEvents();
m_nPatternDelay = 0;
@@ -758,8 +758,16 @@
if (m_nNextRow >= Patterns[m_nPattern].GetNumRows())
{
if (!(m_dwSongFlags & SONG_PATTERNLOOP)) m_nNextPattern = m_nCurrentPattern + 1;
+ m_bPatternTransitionOccurred = true;
m_nNextRow = 0;
- m_bPatternTransitionOccurred=true;
+
+ // FT2 idiosyncrasy: When E60 is used on a pattern row x, the following pattern also starts from row x
+ // instead of the beginning of the pattern, unless there was a Dxx or Cxx effect.
+ if(IsCompatibleMode(TRK_FASTTRACKER2))
+ {
+ m_nNextRow = m_nNextPatStartRow;
+ m_nNextPatStartRow = 0;
+ }
}
// Reset channel values
MODCHANNEL *pChn = Chn;
@@ -786,14 +794,16 @@
m_dwSongFlags |= SONG_FIRSTTICK;
//End of row? stop pattern step (aka "play row").
- if (m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay+1) + m_nFrameDelay - 1) {
- #ifdef MODPLUG_TRACKER
- if (m_dwSongFlags & SONG_STEP) {
+#ifdef MODPLUG_TRACKER
+ if (m_nTickCount >= m_nMusicSpeed * (m_nPatternDelay + 1) + m_nFrameDelay - 1)
+ {
+ if (m_dwSongFlags & SONG_STEP)
+ {
m_dwSongFlags &= ~SONG_STEP;
m_dwSongFlags |= SONG_PAUSED;
}
- #endif // MODPLUG_TRACKER
}
+#endif // MODPLUG_TRACKER
if (m_nTickCount)
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|