From: <rel...@us...> - 2009-06-12 16:25:58
|
Revision: 267 http://modplug.svn.sourceforge.net/modplug/?rev=267&view=rev Author: relabsoluness Date: 2009-06-12 16:25:54 +0000 (Fri, 12 Jun 2009) Log Message: ----------- . XM/IT/MPTM: Fixed a bug in reading an extension. This broke the extension search after reading that entry, although the affected entry has been the last extension in the write order. (merged from rev. 263) . Pattern tab: It's now possible to use the old note fade behaviour when playing notes in pattern tab(see setup->general). (merged from rev. 264) . Pattern tab: Fixed wrong interpretations of "Old style pattern context menu"-option. (merged partly from rev. 262) ? Added validations to song/instrument extension reading and refactored related code. Modified Paths: -------------- branches/1.17.02.53x/mptrack/MainFrm.cpp branches/1.17.02.53x/mptrack/Mainfrm.h branches/1.17.02.53x/mptrack/Moptions.cpp branches/1.17.02.53x/mptrack/View_pat.cpp branches/1.17.02.53x/mptrack/misc_util.h branches/1.17.02.53x/mptrack/version.h branches/1.17.02.53x/soundlib/Load_it.cpp branches/1.17.02.53x/soundlib/Load_xm.cpp branches/1.17.02.53x/soundlib/Sampleio.cpp branches/1.17.02.53x/soundlib/Sndfile.h Modified: branches/1.17.02.53x/mptrack/MainFrm.cpp =================================================================== --- branches/1.17.02.53x/mptrack/MainFrm.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/MainFrm.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -425,6 +425,9 @@ gnMidiPatternLen = GetPrivateProfileLong("MIDI Settings", "MidiImportPatLen", gnMidiPatternLen, iniFile); m_dwPatternSetup = GetPrivateProfileDWord("Pattern Editor", "PatternSetup", m_dwPatternSetup, iniFile); + if(gcsPreviousVersion != "" && MptVersion::ToNum(gcsPreviousVersion) < MAKE_VERSION_NUMERIC(1,17,02,50)) + m_dwPatternSetup |= PATTERN_NOTEFADE; + m_nRowSpacing = GetPrivateProfileDWord("Pattern Editor", "RowSpacing", 16, iniFile); m_nRowSpacing2 = GetPrivateProfileDWord("Pattern Editor", "RowSpacing2", 4, iniFile); gbLoopSong = GetPrivateProfileDWord("Pattern Editor", "LoopSong", true, iniFile); @@ -541,6 +544,7 @@ RegQueryValueEx(key, "MidiSetup", NULL, &dwREG_DWORD, (LPBYTE)&m_dwMidiSetup, &dwDWORDSize); RegQueryValueEx(key, "MidiDevice", NULL, &dwREG_DWORD, (LPBYTE)&m_nMidiDevice, &dwDWORDSize); RegQueryValueEx(key, "PatternSetup", NULL, &dwREG_DWORD, (LPBYTE)&m_dwPatternSetup, &dwDWORDSize); + m_dwPatternSetup |= PATTERN_NOTEFADE; // Set flag to maintain old behaviour(was changed in 1.17.02.50). RegQueryValueEx(key, "RowSpacing", NULL, &dwREG_DWORD, (LPBYTE)&m_nRowSpacing, &dwDWORDSize); RegQueryValueEx(key, "RowSpacing2", NULL, &dwREG_DWORD, (LPBYTE)&m_nRowSpacing2, &dwDWORDSize); RegQueryValueEx(key, "LoopSong", NULL, &dwREG_DWORD, (LPBYTE)&gbLoopSong, &dwDWORDSize); Modified: branches/1.17.02.53x/mptrack/Mainfrm.h =================================================================== --- branches/1.17.02.53x/mptrack/Mainfrm.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/Mainfrm.h 2009-06-12 16:25:54 UTC (rev 267) @@ -206,6 +206,7 @@ #define PATTERN_OLDCTXMENUSTYLE 0x800000 #define PATTERN_SYNCMUTE 0x1000000 #define PATTERN_AUTODELAY 0x2000000 +#define PATTERN_NOTEFADE 0x4000000 // Keyboard Setup Modified: branches/1.17.02.53x/mptrack/Moptions.cpp =================================================================== --- branches/1.17.02.53x/mptrack/Moptions.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/Moptions.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -601,6 +601,7 @@ OPTGEN_PATTERNCTXMENUSTYLE, OPTGEN_SYNCMUTE, OPTGEN_AUTODELAY, + OPTGEN_PATNOTEFADE, OPTGEN_MAXOPTIONS }; @@ -636,6 +637,7 @@ {"Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."}, {"Maintain sample sync on mute", "Samples continue to be processed when channels are muted (like in IT2 and FT2)"}, {"Automatic delay commands", "Automatically insert appropriate note-delay commands when recording notes during live playback."}, + {"Note fade on key up", "Enable to fade/stop notes on key up in pattern tab." } }; @@ -697,6 +699,7 @@ case OPTGEN_SYNCMUTE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_SYNCMUTE); break; case OPTGEN_AUTODELAY: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_AUTODELAY); break; + case OPTGEN_PATNOTEFADE: bCheck = (CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE); break; } m_CheckList.SetCheck(i, (bCheck) ? TRUE : FALSE); } @@ -754,6 +757,7 @@ case OPTGEN_PATTERNCTXMENUSTYLE: mask = PATTERN_OLDCTXMENUSTYLE; break; case OPTGEN_SYNCMUTE: mask = PATTERN_SYNCMUTE; break; case OPTGEN_AUTODELAY: mask = PATTERN_AUTODELAY; break; + case OPTGEN_PATNOTEFADE: mask = PATTERN_NOTEFADE; break; } if (bCheck) CMainFrame::m_dwPatternSetup |= mask; else CMainFrame::m_dwPatternSetup &= ~mask; Modified: branches/1.17.02.53x/mptrack/View_pat.cpp =================================================================== --- branches/1.17.02.53x/mptrack/View_pat.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/View_pat.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -3787,8 +3787,12 @@ pModDoc->NoteOff(0, TRUE, ins, m_dwCursor & 0xFFFF); } else - pModDoc->NoteOff(note, FALSE, ins, GetChanFromCursor(m_dwCursor)); - //pModDoc->NoteOff(note, TRUE, ins, (m_dwCursor & 0xFFFF) >> 3); + { + if(CMainFrame::m_dwPatternSetup & PATTERN_NOTEFADE) + pModDoc->NoteOff(note, TRUE, ins, GetChanFromCursor(m_dwCursor)); + else + pModDoc->NoteOff(note, FALSE, ins, GetChanFromCursor(m_dwCursor)); + } } //Enter note off in pattern? @@ -4518,11 +4522,8 @@ bool CViewPattern::BuildMiscCtxMenu(HMENU hMenu, CInputHandler* ih) //----------------------------------------------------------------- { - if (CMainFrame::m_dwPatternSetup & PATTERN_OLDCTXMENUSTYLE) return false; - AppendMenu(hMenu, MF_STRING, ID_SHOWTIMEATROW, "Show row play time\t" + ih->GetKeyTextFromCommand(kcTimeAtRow)); return true; - } bool CViewPattern::BuildSelectionCtxMenu(HMENU hMenu, CInputHandler* ih) @@ -4701,9 +4702,6 @@ bool CViewPattern::BuildChannelControlCtxMenu(HMENU hMenu) //-------------------------------------------------------------------- { - if (CMainFrame::m_dwPatternSetup&PATTERN_OLDCTXMENUSTYLE) return false; - //Not doing the menuentries if opted to use old style menu style. - AppendMenu(hMenu, MF_SEPARATOR, 0, ""); AppendMenu(hMenu, MF_STRING, ID_PATTERN_DUPLICATECHANNEL, "Duplicate this channel"); Modified: branches/1.17.02.53x/mptrack/misc_util.h =================================================================== --- branches/1.17.02.53x/mptrack/misc_util.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/misc_util.h 2009-06-12 16:25:54 UTC (rev 267) @@ -42,10 +42,34 @@ // Size of the array must be known at compile time. template <size_t size> inline void SetNullTerminator(char (&buffer)[size]) +//------------------------------------------------- { STATIC_ASSERT(size > 0); buffer[size-1] = 0; } +// Limits 'val' to given range. If 'val' is less than 'lowerLimit', 'val' is set to value 'lowerLimit'. +// Similarly if 'val' is greater than 'upperLimit', 'val' is set to value 'upperLimit'. +// If 'lowerLimit' > 'upperLimit', 'val' won't be modified. +template<class T, class C> +inline void Limit(T& val, const C lowerLimit, const C upperLimit) +//--------------------------------------------------------------- +{ + if(lowerLimit > upperLimit) return; + if(val < lowerLimit) val = lowerLimit; + else if(val > upperLimit) val = upperLimit; +} + + +// Like Limit, but with upperlimit only. +template<class T, class C> +inline void LimitMax(T& val, const C upperLimit) +//---------------------------------------------- +{ + if(val > upperLimit) + val = upperLimit; +} + + #endif Modified: branches/1.17.02.53x/mptrack/version.h =================================================================== --- branches/1.17.02.53x/mptrack/version.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/mptrack/version.h 2009-06-12 16:25:54 UTC (rev 267) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 17 #define VER_MINOR 02 -#define VER_MINORMINOR 53 +#define VER_MINORMINOR 54 //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: branches/1.17.02.53x/soundlib/Load_it.cpp =================================================================== --- branches/1.17.02.53x/soundlib/Load_it.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Load_it.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -847,8 +847,7 @@ // Extra info data __int32 fcode = 0; - __int16 fsize = 0; - BYTE * ptr = (BYTE *)(lpStream + streamPos); + LPCBYTE ptr = lpStream + min(streamPos, dwMemLength); if (streamPos <= dwMemLength - 4) { fcode = (*((__int32 *)ptr)); @@ -863,7 +862,7 @@ i = 1; // parse file - while( ptr + 4 <= (BYTE *)(lpStream + dwMemLength) && i <= m_nInstruments ){ + while( uintptr_t(ptr - lpStream) <= dwMemLength - 4 && i <= m_nInstruments ){ fcode = (*((__int32 *)ptr)); // read field code @@ -876,16 +875,7 @@ default: ptr += sizeof(__int32); // jump field code - if(ptr + 2 > (BYTE *)(lpStream + dwMemLength)) return FALSE; - fsize = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[i], fcode, fsize); - if(fadr && fcode != 'K[..') // copy field data in instrument's header - { - if(ptr + fsize > (BYTE *)(lpStream + dwMemLength)) return FALSE; - memcpy(fadr,ptr,fsize); // (except for keyboard mapping) - } - ptr += fsize; // jump field + ReadExtendedInstrumentProperty(Headers[i], fcode, ptr, lpStream + dwMemLength); break; } } @@ -893,7 +883,7 @@ //HACK: if we fail on i <= m_nInstruments above, arrive here without having set fcode as appropriate, // hence the code duplication. - if (ptr + 4 <= (BYTE *)(lpStream + dwMemLength)) { + if ( (uintptr_t)(ptr - lpStream) <= dwMemLength - 4 ) { fcode = (*((__int32 *)ptr)); } @@ -917,8 +907,8 @@ } // -! NEW_FEATURE#0023 -BOOL CSoundFile::ReadIT(const BYTE *lpStream, const DWORD dwMemLength) -//-------------------------------------------------------------- +BOOL CSoundFile::ReadIT(const LPCBYTE lpStream, const DWORD dwMemLength) +//---------------------------------------------------------------------- { ITFILEHEADER *pifh = (ITFILEHEADER *)lpStream; @@ -1320,55 +1310,18 @@ ITSAMPLESTRUCT *pis = (ITSAMPLESTRUCT *)(lpStream+smppos[pifh->smpnum-1]); dwMemPos = pis->samplepointer + lastSampleSize; - // Get file pointer to match the first byte of extra settings informations __int16 size = 0; - __int32 code = 0; - __int16 size = 0; - BYTE * ptr = NULL; - if(dwMemPos < dwMemLength) { - ptr = (BYTE *)(lpStream + dwMemPos); - code = (*((__int32 *)ptr));; + // Load instrument and song extensions. + if(mptStartPos >= dwMemPos) + { + LPCBYTE ptr = LoadExtendedInstrumentProperties(lpStream + dwMemPos, lpStream + mptStartPos, &interpretModplugmade); + LoadExtendedSongProperties(GetType(), ptr, lpStream, mptStartPos, &interpretModplugmade); } - - // Instrument extensions - if( code == 'MPTX' ){ - interpretModplugmade = true; - ptr += sizeof(__int32); // jump extension header code - while( (DWORD)(ptr - lpStream) < mptStartPos ){ //Loop 'till beginning of end of file/mpt specific looking for inst. extensions - code = (*((__int32 *)ptr)); // read field code - if (code == 'MPTS') { //Reached song extensions, break out of this loop - break; - } - - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - for(UINT nins=1; nins<=m_nInstruments; nins++){ - if(Headers[nins]){ - // get field's adress in instrument's header - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[nins], code, size); - // copy field data in instrument's header (except for keyboard mapping) - if(fadr && code != 'K[..') memcpy(fadr,ptr,size); - // jump field - ptr += size; - } - } - //end rewbs.instroVSTi - } - } // -! NEW_FEATURE#0027 - // Song extensions - if( code == 'MPTS' ) - { - interpretModplugmade = true; - LoadExtendedSongProperties(GetType(), ptr, lpStream, mptStartPos); - } + // Reading Patterns Patterns.ResizeArray(max(MAX_PATTERNS, npatterns)); - - // Reading Patterns for (UINT npat=0; npat<npatterns; npat++) { if ((!patpos[npat]) || ((DWORD)patpos[npat] >= dwMemLength - 4)) @@ -3674,53 +3627,143 @@ return; } +LPCBYTE CSoundFile::LoadExtendedInstrumentProperties(const LPCBYTE pStart, + const LPCBYTE pEnd, + bool* pInterpretMptMade) +//--------------------------------------------------------------------------- +{ + if( pStart == NULL || pEnd <= pStart || uintptr_t(pEnd - pStart) < 4) + return NULL; -void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const BYTE* lpStream, const size_t searchlimit) -//-------------------------------------------------- + int32 code = 0; + int16 size = 0; + LPCBYTE ptr = pStart; + + memcpy(&code, ptr, sizeof(code)); + + if(code != 'MPTX') + return NULL; + + // Found MPTX, interpret the file MPT made. + if(pInterpretMptMade != NULL) + *pInterpretMptMade = true; + + ptr += sizeof(int32); // jump extension header code + while( ptr < pEnd && uintptr_t(pEnd-ptr) >= 4) //Loop 'till beginning of end of file/mpt specific looking for inst. extensions + { + memcpy(&code, ptr, sizeof(code)); // read field code + if (code == 'MPTS') //Reached song extensions, break out of this loop + return ptr; + + ptr += sizeof(code); // jump field code + + if((uintptr_t)(pEnd - ptr) < 2) + return NULL; + + memcpy(&size, ptr, sizeof(size)); // read field size + ptr += sizeof(size); // jump field size + + if(IsValidSizeField(ptr, pEnd, size) == false) + return NULL; + + for(UINT nins=1; nins<=m_nInstruments; nins++) + { + if(Headers[nins]) + ReadInstrumentExtensionField(Headers[nins], ptr, code, size); + } + } + + return NULL; +} + + +void CSoundFile::LoadExtendedSongProperties(const MODTYPE modtype, + LPCBYTE ptr, + const LPCBYTE lpStream, + const size_t searchlimit, + bool* pInterpretMptMade) +//------------------------------------------------------------------- { + if(searchlimit < 6 || ptr == NULL || ptr < lpStream || uintptr_t(ptr - lpStream) > searchlimit - 4) + return; + + const LPCBYTE pEnd = lpStream + searchlimit; + int32 code = 0; int16 size = 0; - ptr += sizeof(int32); // jump extension header code - while( (DWORD)(ptr + 6 - lpStream) <= searchlimit ) //Loop until given limit. + + memcpy(&code, ptr, sizeof(code)); + + if(code != 'MPTS') + return; + + // Found MPTS, interpret the file MPT made. + if(pInterpretMptMade != NULL) + *pInterpretMptMade = true; + + + // Case macros. + #define CASE(id, data) \ + case id: fadr = reinterpret_cast<BYTE*>(&data); nMaxReadCount = min(size, sizeof(data)); break; + #define CASE_NOTXM(id, data) \ + case id: if(modtype != MOD_TYPE_XM) {fadr = reinterpret_cast<BYTE*>(&data); nMaxReadCount = min(size, sizeof(data));} break; + + ptr += sizeof(code); // jump extension header code + while( uintptr_t(ptr - lpStream) <= searchlimit-6 ) //Loop until given limit. { - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - if(size < 0) break; - ptr += sizeof(__int16); // jump field size + code = (*((int32 *)ptr)); // read field code + ptr += sizeof(int32); // jump field code + size = (*((int16 *)ptr)); // read field size + ptr += sizeof(int16); // jump field size + if(IsValidSizeField(ptr, pEnd, size) == false) + break; + + size_t nMaxReadCount = 0; BYTE * fadr = NULL; - switch (code) { // interpret field code - case 'DT..': fadr = reinterpret_cast<BYTE*>(&m_nDefaultTempo); break; - case 'RPB.': fadr = reinterpret_cast<BYTE*>(&m_nRowsPerBeat); break; - case 'RPM.': fadr = reinterpret_cast<BYTE*>(&m_nRowsPerMeasure); break; - case 'C...': if(modtype != MOD_TYPE_XM) fadr = reinterpret_cast<BYTE*>(&m_nChannels); break; - case 'TM..': fadr = reinterpret_cast<BYTE*>(&m_nTempoMode); break; - case 'PMM.': fadr = reinterpret_cast<BYTE*>(&m_nMixLevels); break; - case 'CWV.': fadr = reinterpret_cast<BYTE*>(&m_dwCreatedWithVersion); break; - case 'LSWV': fadr = reinterpret_cast<BYTE*>(&m_dwLastSavedWithVersion); break; - case 'SPA.': fadr = reinterpret_cast<BYTE*>(&m_nSamplePreAmp); break; - case 'VSTV': fadr = reinterpret_cast<BYTE*>(&m_nVSTiVolume); break; - case 'DGV.': fadr = reinterpret_cast<BYTE*>(&m_nDefaultGlobalVolume); break; - case 'RP..': if(modtype != MOD_TYPE_XM) fadr = reinterpret_cast<BYTE*>(&m_nRestartPos); break; - case 'MSF.': fadr = reinterpret_cast<BYTE*>(&m_ModFlags); break; - case 'MIMA': - if(DWORD(ptr - lpStream + DWORD(size)) > searchlimit) - MessageBox(NULL, "Error: Bad MIMA datasizefield", NULL, MB_ICONERROR); - else - { - GetMIDIMapper().Unserialize(ptr, size); - ptr += size; - } - break; + switch (code) // interpret field code + { + CASE('DT..', m_nDefaultTempo); + CASE('RPB.', m_nRowsPerBeat); + CASE('RPM.', m_nRowsPerMeasure); + CASE_NOTXM('C...', m_nChannels); + CASE('TM..', m_nTempoMode); + CASE('PMM.', m_nMixLevels); + CASE('CWV.', m_dwCreatedWithVersion); + CASE('LSWV', m_dwLastSavedWithVersion); + CASE('SPA.', m_nSamplePreAmp); + CASE('VSTV', m_nVSTiVolume); + CASE('DGV.', m_nDefaultGlobalVolume); + CASE_NOTXM('RP..', m_nRestartPos); + CASE('MSF.', m_ModFlags); + case 'MIMA': GetMIDIMapper().Unserialize(ptr, size); break; } - if (fadr != NULL && ptr - lpStream + DWORD(size) <= searchlimit) { // if field code recognized - memcpy(fadr,ptr,size); // read field data - } + if (fadr != NULL) // if field code recognized + memcpy(fadr,ptr,nMaxReadCount); // read field data + ptr += size; // jump field data } + + // Validate read values. + Limit(m_nDefaultTempo, GetModSpecifications().tempoMin, GetModSpecifications().tempoMax); + //m_nRowsPerBeat + //m_nRowsPerMeasure + LimitMax(m_nChannels, GetModSpecifications().channelsMax); + //m_nTempoMode + //m_nMixLevels + //m_dwCreatedWithVersion + //m_dwLastSavedWithVersion + //m_nSamplePreAmp + //m_nVSTiVolume + //m_nDefaultGlobalVolume); + //m_nRestartPos + //m_ModFlags + + + #undef CASE + #undef CASE_NOTXM } Modified: branches/1.17.02.53x/soundlib/Load_xm.cpp =================================================================== --- branches/1.17.02.53x/soundlib/Load_xm.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Load_xm.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -611,54 +611,16 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwMemLength) return TRUE; - // Get file pointer to match the first byte of extra settings informations - BYTE * ptr = (BYTE *)(lpStream + dwMemPos); + bool bInterpretMptMade = false; + LPCBYTE ptr = lpStream + dwMemPos; + if(m_nInstruments) + ptr = LoadExtendedInstrumentProperties(ptr, lpStream+dwMemLength, &bInterpretMptMade); - // Seek for supported extended settings header - __int16 size = 0; - __int32 code = (*((__int32 *)ptr)); + LoadExtendedSongProperties(GetType(), ptr, lpStream, dwMemLength, &bInterpretMptMade); - // Instrument extensions - if( code == 'MPTX' && m_nInstruments ){ - ptr += sizeof(__int32); // jump extension header code - while( (DWORD)(ptr - lpStream) < dwMemLength ){ //Loop 'till end of file looking for inst. extensions + if(bInterpretMptMade && m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) + SetModFlag(MSF_MIDICC_BUGEMULATION, true); - code = (*((__int32 *)ptr)); // read field code - if (code == 'MPTS') { //Reached song extensions, break out of this loop - break; - } - - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - for(UINT nins=1; nins<=m_nInstruments; nins++){ - if(Headers[nins]){ - // get field's adress in instrument's header - BYTE * fadr = GetInstrumentHeaderFieldPointer(Headers[nins], code, size); - // copy field data in instrument's header (except for keyboard mapping) - if(fadr && code != 'K[..') memcpy(fadr,ptr,size); - // jump field - ptr += size; - } - } - //end rewbs.instroVSTi - } - } -// -! NEW_FEATURE#0027 - - // Song extensions - if( code == 'MPTS' ) - { - LoadExtendedSongProperties(MOD_TYPE_XM, ptr, lpStream, dwMemLength); - if(m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) - SetModFlag(MSF_MIDICC_BUGEMULATION, true); - } - - - - - return TRUE; } Modified: branches/1.17.02.53x/soundlib/Sampleio.cpp =================================================================== --- branches/1.17.02.53x/soundlib/Sampleio.cpp 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Sampleio.cpp 2009-06-12 16:25:54 UTC (rev 267) @@ -1297,28 +1297,8 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return TRUE; - // Compute current file pointer position - BYTE * ptr = (BYTE *)(lpMemFile+dwMemPos); + ReadExtendedInstrumentProperties(penv, lpMemFile + dwMemPos, dwFileLength - dwMemPos); - // Seek for supported extended settings header - if( (*((__int32 *)ptr)) == 'MPTX' && penv ){ - __int16 size; - __int32 code; - ptr += sizeof(__int32); // jump extension header code - - while( (DWORD)(ptr - lpMemFile) < dwFileLength ){ - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - BYTE * fadr = GetInstrumentHeaderFieldPointer(penv, code, size); - if(fadr && code != 'K[..') // copy field data in instrument's header - memcpy(fadr,ptr,size); // (except for keyboard mapping) - ptr += size; // jump field - } - } - // -! NEW_FEATURE#0027 return TRUE; @@ -1827,28 +1807,8 @@ // Leave if no extra instrument settings are available (end of file reached) if(dwMemPos >= dwFileLength) return TRUE; - // Get file pointer to match the first byte of extra settings informations - ptr = (BYTE *)(lpMemFile+dwMemPos); + ReadExtendedInstrumentProperties(penv, lpMemFile + dwMemPos, dwFileLength - dwMemPos); - // Seek for supported extended settings header - if( (*((__int32 *)ptr)) == 'MPTX' && penv ){ - __int16 size; - __int32 code; - ptr += sizeof(__int32); // jump extension header code - - while( (DWORD)(ptr - lpMemFile) < dwFileLength ){ - code = (*((__int32 *)ptr)); // read field code - ptr += sizeof(__int32); // jump field code - size = (*((__int16 *)ptr)); // read field size - ptr += sizeof(__int16); // jump field size - - BYTE * fadr = GetInstrumentHeaderFieldPointer(penv, code, size); - if(fadr && code != 'K[..') // copy field data in instrument's header - memcpy(fadr,ptr,size); // (except for keyboard mapping) - ptr += size; // jump field - } - } - // -! NEW_FEATURE#0027 return TRUE; @@ -2043,6 +2003,73 @@ } + +bool IsValidSizeField(const LPCBYTE pData, const LPCBYTE pEnd, const int16 size) +//------------------------------------------------------------------------------ +{ + if(size < 0 || (uintptr_t)(pEnd - pData) < (uintptr_t)size) + return false; + else + return true; +} + + +void ReadInstrumentExtensionField(INSTRUMENTHEADER* penv, LPCBYTE& ptr, const int32 code, const int16 size) +//------------------------------------------------------------------------------------------------------------ +{ + // get field's address in instrument's header + BYTE* fadr = GetInstrumentHeaderFieldPointer(penv, code, size); + + if(fadr && code != 'K[..') // copy field data in instrument's header + memcpy(fadr,ptr,size); // (except for keyboard mapping) + ptr += size; // jump field +} + + +void ReadExtendedInstrumentProperty(INSTRUMENTHEADER* penv, const int32 code, LPCBYTE& pData, const LPCBYTE pEnd) +//--------------------------------------------------------------------------------------------------------------- +{ + if(pEnd < pData || uintptr_t(pEnd - pData) < 2) + return; + + int16 size; + memcpy(&size, pData, sizeof(size)); // read field size + pData += sizeof(size); // jump field size + + if(IsValidSizeField(pData, pEnd, size) == false) + return; + + ReadInstrumentExtensionField(penv, pData, code, size); +} + + +void ReadExtendedInstrumentProperties(INSTRUMENTHEADER* penv, const LPCBYTE pDataStart, const size_t nMemLength) +//-------------------------------------------------------------------------------------------------------------- +{ + if(penv == 0 || pDataStart == 0 || nMemLength < 4) + return; + + LPCBYTE pData = pDataStart; + const LPCBYTE pEnd = pDataStart + nMemLength; + + int32 code; + memcpy(&code, pData, sizeof(code)); + + // Seek for supported extended settings header + if( code == 'MPTX' ) + { + pData += sizeof(code); // jump extension header code + + while( (uintptr_t)(pData - pDataStart) <= nMemLength - 4) + { + memcpy(&code, pData, sizeof(code)); // read field code + pData += sizeof(code); // jump field code + ReadExtendedInstrumentProperty(penv, code, pData, pEnd); + } + } +} + + /////////////////////////////////////////////////////////////////////////////////////////////////// // 8SVX Samples Modified: branches/1.17.02.53x/soundlib/Sndfile.h =================================================================== --- branches/1.17.02.53x/soundlib/Sndfile.h 2009-06-09 19:59:04 UTC (rev 266) +++ branches/1.17.02.53x/soundlib/Sndfile.h 2009-06-12 16:25:54 UTC (rev 267) @@ -1086,8 +1086,13 @@ void WriteInstrumentPropertyForAllInstruments(__int32 code, __int16 size, FILE* f, INSTRUMENTHEADER* instruments[], UINT nInstruments); void SaveExtendedInstrumentProperties(INSTRUMENTHEADER *instruments[], UINT nInstruments, FILE* f); void SaveExtendedSongProperties(FILE* f); - void LoadExtendedSongProperties(const MODTYPE modtype, BYTE*& ptr, const BYTE* startpos, const size_t seachlimit); + void LoadExtendedSongProperties(const MODTYPE modtype, LPCBYTE ptr, const LPCBYTE startpos, const size_t seachlimit, bool* pInterpretMptMade = NULL); + // 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); + #endif // MODPLUG_NO_FILESAVE // MOD Convert function UINT GetBestSaveFormat() const; @@ -1515,4 +1520,18 @@ #endif +// Used in instrument/song extension reading to make sure the size field is valid. +bool IsValidSizeField(const LPCBYTE pData, const LPCBYTE pEnd, const int16 size); + +// Read instrument property with 'code' and 'size' from 'ptr' to instrument 'penv'. +// Note: (ptr, size) pair must be valid (e.g. can read 'size' bytes from 'ptr') +void ReadInstrumentExtensionField(INSTRUMENTHEADER* penv, LPCBYTE& ptr, const int32 code, const int16 size); + +// Read instrument property with 'code' from 'pData' to instrument 'penv'. +void ReadExtendedInstrumentProperty(INSTRUMENTHEADER* penv, const int32 code, LPCBYTE& pData, const LPCBYTE pEnd); + +// Read extended instrument properties from 'pDataStart' to instrument 'penv'. +void ReadExtendedInstrumentProperties(INSTRUMENTHEADER* penv, const LPCBYTE pDataStart, const size_t nMemLength); + + #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |