From: <sag...@us...> - 2011-04-08 22:25:14
|
Revision: 843 http://modplug.svn.sourceforge.net/modplug/?rev=843&view=rev Author: saga-games Date: 2011-04-08 22:25:07 +0000 (Fri, 08 Apr 2011) Log Message: ----------- [Fix] J2B Loader: Empty sample slots are now treated correct in new J2B (AM) files). [Fix] DMF Loader: Many many improvements to portamento, pattersn with variable number of tracks and other effects. [Mod] OpenMPT: Version is now 1.19.01.01 Modified Paths: -------------- trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/load_j2b.cpp Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2011-04-08 22:23:19 UTC (rev 842) +++ trunk/OpenMPT/mptrack/version.h 2011-04-08 22:25:07 UTC (rev 843) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 19 #define VER_MINOR 01 -#define VER_MINORMINOR 00 +#define VER_MINORMINOR 01 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-08 22:23:19 UTC (rev 842) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-08 22:25:07 UTC (rev 843) @@ -12,6 +12,9 @@ /////////////////////////////////////////////////////// #include "stdafx.h" #include "Loaders.h" +#ifdef MODPLUG_TRACKER +#include "../mptrack/Moddoc.h" +#endif // MODPLUG_TRACKER //#define DMFLOG @@ -86,6 +89,16 @@ #endif +// Convert portamento value (not very accurate, to say the least) +uint8 DMFporta2MPT(uint8 val) +//--------------------------- +{ + if(val <= 0x0F) + return (val | 0xF0); + else + return (val / 4); +} + bool CSoundFile::ReadDMF(const BYTE *lpStream, const DWORD dwMemLength) //--------------------------------------------------------------------- { @@ -102,10 +115,25 @@ memcpy(m_szNames[0], pfh->songname, 30); SpaceToNullStringFixed<30>(m_szNames[0]); m_nType = MOD_TYPE_DMF; + m_dwSongFlags = SONG_LINEARSLIDES | SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS; m_nChannels = 0; #ifdef DMFLOG Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength); #endif + +#ifdef MODPLUG_TRACKER + if(GetpModDoc() != nullptr) + { + FileHistory mptHistory; + MemsetZero(mptHistory); + mptHistory.loadDate.tm_mday = CLAMP(pfh->date[0], 0, 31); + mptHistory.loadDate.tm_mon = CLAMP(pfh->date[1], 1, 12) - 1; + mptHistory.loadDate.tm_year = pfh->date[2]; + GetpModDoc()->GetFileHistory()->clear(); + GetpModDoc()->GetFileHistory()->push_back(mptHistory); + } +#endif // MODPLUG_TRACKER + while (dwMemPos + 7 < dwMemLength) { DWORD id = *((LPDWORD)(lpStream+dwMemPos)); @@ -135,7 +163,7 @@ if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1; Order.resize(nseq, Order.GetInvalidPatIndex()); if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart; - for (UINT i = 0; i < nseq; i++) Order[i] = (PATTERNINDEX)sequ->sequ[i]; + for (UINT i = 0; i < nseq - 2; i++) Order[i] = (PATTERNINDEX)sequ->sequ[i]; } dwMemPos += sequ->seqsize + 8; break; @@ -150,10 +178,12 @@ if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit; numpat = patt->numpat; if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS; + m_nChannels = patt->tracks; if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo; if (m_nChannels > 32) m_nChannels = 32; if (m_nChannels < 1) m_nChannels = 1; + for (UINT npat=0; npat<numpat; npat++) { DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos); @@ -163,13 +193,19 @@ UINT tracks = pt->tracks; if (tracks > 32) tracks = 32; UINT ticks = pt->ticks; - if (ticks > 256) ticks = 256; - if (ticks < 16) ticks = 16; + if (ticks > MAX_PATTERN_ROWS) ticks = MAX_PATTERN_ROWS; + if (ticks < 1) ticks = 1; dwPos += 8; if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; if(Patterns.Insert(npat, ticks)) goto dmfexit; MODCOMMAND *m = Patterns[npat]; + // If pattern "width" changes, leftover voices are killed: + for(CHANNELINDEX nChn = tracks; nChn < m_nChannels; nChn++) + { + m[nChn].note = NOTE_NOTECUT; + } + DWORD d = dwPos; dwPos += pt->jmpsize; UINT ttype = 1; @@ -217,8 +253,17 @@ if (info & 0x20) { cmd.note = lpStream[d++]; - if ((cmd.note) && (cmd.note < 0xfe)) cmd.note &= 0x7f; - if ((cmd.note) && (cmd.note < 128)) cmd.note += 24; + if (cmd.note >= 1 && cmd.note <= 108) + { + cmd.note += 24; + } else if (cmd.note >= 129 && cmd.note <= 236) + { + // "ghost notes" for portamento that are actually not played... how the hell should we treat them?! + cmd.note += 24; + } else if (cmd.note == 255) + { + cmd.note = NOTE_NOTECUT; + } } // Volume if (info & 0x10) @@ -226,7 +271,7 @@ cmd.volcmd = VOLCMD_VOLUME; cmd.vol = (lpStream[d++]+3)>>2; } - // Effect 1 + // Effect 1 - Instrument if (info & 0x08) { BYTE efx = lpStream[d++]; @@ -234,20 +279,23 @@ switch(efx) { // 1: Key Off - case 1: if (!cmd.note) cmd.note = 0xFE; break; - // 2: Set Loop - // 4: Sample Delay + case 1: if (!cmd.note) cmd.note = NOTE_NOTECUT; break; + // 2: Stop Sample Loop + case 2: if (!cmd.note) cmd.note = NOTE_KEYOFF; break; + // 4: Sample Delay, in 1/256th rows case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 5: Retrig + // 5: Retrig, in 1/256th rows case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break; // 6: Offset case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break; + // 10: Tekkno Invert + case 10: cmd.command = CMD_S3MCMDEX; cmd.param = 0x9F; break; #ifdef DMFLOG default: Log("FX1: %02X.%02X\n", efx, eval); #endif } } - // Effect 2 + // Effect 2 - Note if (info & 0x04) { BYTE efx = lpStream[d++]; @@ -261,22 +309,22 @@ // 3: Arpeggio case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break; // 4: Portamento Up - case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; + case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = DMFporta2MPT(eval); break; // 5: Portamento Down - case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; + case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = DMFporta2MPT(eval); break; // 6: Tone Portamento - case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = eval; break; + case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = DMFporta2MPT(eval); break; // 8: Vibrato case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break; - // 12: Note cut + // 12: Note cut, in 1/256th rows case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; } - else if (!cmd.note) { cmd.note = 0xfe; } break; + else if (!cmd.note) { cmd.note = NOTE_NOTECUT; } break; #ifdef DMFLOG default: Log("FX2: %02X.%02X\n", efx, eval); #endif } } - // Effect 3 + // Effect 3 - Volume if (info & 0x02) { BYTE efx = lpStream[d++]; @@ -296,7 +344,7 @@ else { cmd.command = CMD_PANNING8; cmd.param = eval; } break; // 8: Pan Slide Left case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval<<4; break; + cmd.command = CMD_PANNINGSLIDE; cmd.param = eval << 4; break; // 9: Pan Slide Right case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break; @@ -305,6 +353,21 @@ #endif } } + + // Note without instrument == just reset pitch, do not retrigger + if(cmd.instr == 0 && cmd.note != NOTE_NONE && NOTE_IS_VALID(cmd.note) && cmd.command != CMD_TONEPORTAMENTO) + { + if(cmd.volcmd == VOLCMD_NONE) + { + cmd.volcmd = VOLCMD_TONEPORTAMENTO; + cmd.vol = 9; + } else + { + cmd.command = CMD_TONEPORTAMENTO; + cmd.param = 0xFF; + } + } + // Store effect if (i < m_nChannels) p[i] = cmd; if (d > dwPos) @@ -389,14 +452,14 @@ DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); MODSAMPLE *psmp = &Samples[iSmp]; psmp->nLength = psh->len; - psmp->nLoopStart = psh->loopstart; - psmp->nLoopEnd = psh->loopend; + psmp->nSustainStart = psh->loopstart; + psmp->nSustainEnd = psh->loopend; psmp->nC5Speed = psh->c3speed; psmp->nGlobalVol = 64; psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256; psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0; if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1; - if (psh->flags & 1) psmp->uFlags |= CHN_LOOP; + if (psh->flags & 1) psmp->uFlags |= CHN_SUSTAINLOOP; smplflags[iSmp] = psh->flags; dwPos += (pfh->version < 8) ? 22 : 30; #ifdef DMFLOG Modified: trunk/OpenMPT/soundlib/load_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2011-04-08 22:23:19 UTC (rev 842) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2011-04-08 22:25:07 UTC (rev 843) @@ -35,6 +35,9 @@ #define AMCHUNKID_AI__ 0x20204941 #define AMCHUNKID_AS__ 0x20205341 +// Header flags +#define AMHEAD_LINEAR 0x01 + // Envelope flags #define AMENV_ENABLED 0x01 #define AMENV_SUSTAIN 0x02 @@ -78,7 +81,7 @@ uint8 channels; uint8 speed; uint8 tempo; - uint32 unknown; // 0x16078035 if original file was MOD, 0xC50100FF for everything else? + uint32 unknown; // 0x16078035 if original file was MOD, 0xC50100FF for everything else? it's 0xFF00FFFF in Carrotus.j2b (AMFF version) uint8 globalvolume; }; @@ -489,7 +492,7 @@ memcpy(m_szNames[0], mainchunk->songname, 32); SpaceToNullStringFixed<31>(m_szNames[0]); m_dwSongFlags = SONG_ITOLDEFFECTS | SONG_ITCOMPATGXX; - if(!(mainchunk->flags & 0x01)) m_dwSongFlags |= SONG_LINEARSLIDES; + if(!(mainchunk->flags & AMHEAD_LINEAR)) m_dwSongFlags |= SONG_LINEARSLIDES; if(mainchunk->channels < 1) return false; m_nChannels = min(mainchunk->channels, MAX_BASECHANNELS); m_nDefaultSpeed = mainchunk->speed; @@ -497,7 +500,7 @@ m_nDefaultGlobalVolume = mainchunk->globalvolume << 1; m_nSamplePreAmp = m_nVSTiVolume = 48; m_nType = MOD_TYPE_J2B; - ASSERT(LittleEndian(mainchunk->unknown) == 0xFF0001C5 || LittleEndian(mainchunk->unknown) == 0x35800716); + ASSERT(LittleEndian(mainchunk->unknown) == 0xFF0001C5 || LittleEndian(mainchunk->unknown) == 0x35800716 || LittleEndian(mainchunk->unknown) == 0xFF00FFFF); // It seems like there's no way to differentiate between // Muted and Surround channels (they're all 0xA0) - might @@ -688,6 +691,11 @@ const size_t nTotalSmps = LittleEndianW(instheader->numsamples); + if(nTotalSmps == 0) + { + MemsetZero(pIns->Keyboard); + } + DWORD dwChunkPos; // read sample sub-chunks (RIFF nesting ftw) @@ -705,15 +713,16 @@ if(LittleEndian(*(uint32 *)(lpStream + dwChunkPos)) != AMCHUNKID_AS__) break; dwChunkPos += 4; + // Moved this stuff here (was below the next ASSERT_CAN_READ_CHUNK) because of instrument 12 in Carrotus.j2b + if(m_nSamples + 1 >= MAX_SAMPLES) + break; + const SAMPLEINDEX nSmp = ++m_nSamples; + ASSERT_CAN_READ_CHUNK(sizeof(AMCHUNK_SAMPLE)); const AMCHUNK_SAMPLE *smpchunk = (AMCHUNK_SAMPLE *)(lpStream + dwChunkPos); if(smpchunk->signature != AMCHUNKID_SAMP) break; // SAMP - if(m_nSamples + 1 >= MAX_SAMPLES) - break; - const SAMPLEINDEX nSmp = ++m_nSamples; - MemsetZero(Samples[nSmp]); memcpy(m_szNames[nSmp], smpchunk->name, 32); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |