From: <sag...@us...> - 2010-06-05 13:13:58
|
Revision: 616 http://modplug.svn.sourceforge.net/modplug/?rev=616&view=rev Author: saga-games Date: 2010-06-05 13:13:51 +0000 (Sat, 05 Jun 2010) Log Message: ----------- [Imp] Orderlist Editor: When inserting patterns at an empty position, the position counter is not increased anymore. [Imp] Pattern Editor: Just like in MPT 1.16, it is now possible again to interpolate between an effect and "nothing". In that case, the same value as the already existing one is repeated between the two rows. [New] Experimental "panic" button on the mainbar. At the moment, it just kills all VSTi and sample voices. [Imp] Added mnemonic codes to the wave export controls. [Fix] S3M Loader: Very short sample loops (4 byte) were not loaded properly. Fixes "a tiny problem.s3m" by \slash. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainbar.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/res/MAINBAR.BMP trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/soundlib/Load_s3m.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2010-06-05 13:13:51 UTC (rev 616) @@ -785,11 +785,12 @@ { rows = pSndFile->Patterns[pat].GetNumRows(); rows = CLAMP(rows, pSndFile->GetModSpecifications().patternRowsMin, pSndFile->GetModSpecifications().patternRowsMax); + nCurOrd++; // only if the current oder is already occupied, create a new pattern at the next position. } - PATTERNINDEX nNewPat = m_pModDoc->InsertPattern(nCurOrd + 1, rows); + PATTERNINDEX nNewPat = m_pModDoc->InsertPattern(nCurOrd, rows); if ((nNewPat != PATTERNINDEX_INVALID) && (nNewPat < pSndFile->Patterns.Size())) { - m_OrderList.SetCurSel(nCurOrd + 1); + m_OrderList.SetCurSel(nCurOrd); m_OrderList.InvalidateRect(NULL, FALSE); SetCurrentPattern(nNewPat); m_pModDoc->SetModified(); @@ -879,12 +880,8 @@ CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); if (pMainFrm) pMainFrm->PauseMod(m_pModDoc); CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); - for (UINT i=0; i<MAX_CHANNELS; i++) - { - pSndFile->Chn[i].nLength = 0; - pSndFile->Chn[i].nROfs = 0; - pSndFile->Chn[i].nLOfs = 0; - } + if(pSndFile) + pSndFile->ResetChannels(); } SwitchToView(); } Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2010-06-05 13:13:51 UTC (rev 616) @@ -89,6 +89,7 @@ ON_COMMAND(ID_ADD_SOUNDBANK, OnAddDlsBank) ON_COMMAND(ID_IMPORT_MIDILIB, OnImportMidiLib) ON_COMMAND(ID_MIDI_RECORD, OnMidiRecord) + ON_COMMAND(ID_PANIC, OnPanic) ON_COMMAND(ID_PLAYER_PAUSE, OnPlayerPause) ON_COMMAND_EX(IDD_TREEVIEW, OnBarCheck) ON_COMMAND_EX(ID_NETLINK_OPENMPTWIKI, OnInternetLink) @@ -2701,6 +2702,18 @@ } +void CMainFrame::OnPanic() +//------------------------ +{ + // Panic button. At the moment, it just resets all VSTi and sample notes. + if(m_pModPlaying && m_pModPlaying->GetSoundFile()) + { + m_pModPlaying->GetSoundFile()->StopAllVsti(); + m_pModPlaying->GetSoundFile()->ResetChannels(); + } +} + + void CMainFrame::OnPrevOctave() //----------------------------- { Modified: trunk/OpenMPT/mptrack/Mainbar.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mainbar.cpp 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/Mainbar.cpp 2010-06-05 13:13:51 UTC (rev 616) @@ -210,6 +210,8 @@ // ID_CONTEXT_HELP, ID_SEPARATOR, //rewbs.reportBug ID_REPORT_BUG, //rewbs.reportBug + ID_SEPARATOR, + ID_PANIC, }; @@ -227,7 +229,7 @@ if (!CToolBar::Create(parent, dwStyle)) return FALSE; if (!LoadBitmap(IDB_MAINBAR)) return FALSE; - if (!SetButtons(MainButtons, sizeof(MainButtons)/sizeof(UINT))) return FALSE; + if (!SetButtons(MainButtons, ARRAYELEMCOUNT(MainButtons))) return FALSE; nCurrentSpeed = 6; nCurrentTempo = 125; Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2010-06-05 13:13:51 UTC (rev 616) @@ -684,6 +684,7 @@ afx_msg void OnPrevOctave(); afx_msg void OnNextOctave(); afx_msg void OnOctaveChanged(); + afx_msg void OnPanic(); afx_msg void OnReportBug(); //rewbs.customKeys afx_msg BOOL OnInternetLink(UINT nID); afx_msg LRESULT OnUpdatePosition(WPARAM, LPARAM lParam); Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2010-06-05 13:13:51 UTC (rev 616) @@ -1098,7 +1098,6 @@ if ((!bItemSelected) || (!m_nDragItem)) return; InvalidateRect(&m_rcDragItem, FALSE); DWORD nItemNo = m_nDragItem & 0xFFFF; - CSoundFile *pSndFile = pModDoc->GetSoundFile(); switch(m_nDragItem & DRAGITEM_MASK) { case DRAGITEM_CHNHEADER: @@ -1282,7 +1281,7 @@ if (m_nDragItem) { DWORD nItem = GetDragItem(point, NULL); - BOOL b = (nItem == m_nDragItem) ? TRUE : FALSE; + bool b = (nItem == m_nDragItem) ? true : false; if (b != m_bInItemRect) { m_bInItemRect = b; @@ -1441,20 +1440,25 @@ } const CHANNELINDEX nNumChn = pModDoc->GetNumChannels(); - UINT nChn = current ? (m_dwCursor&0xFFFF)>>3 : (m_nMenuParam&0xFFFF)>>3; - if (nChn >= nNumChn) { + const CHANNELINDEX nChn = current ? (m_dwCursor&0xFFFF)>>3 : (m_nMenuParam&0xFFFF)>>3; + if (nChn >= nNumChn) + { return; } - if (pModDoc->IsChannelSolo(nChn)) { + if (pModDoc->IsChannelSolo(nChn)) + { bool nChnIsOnlyUnMutedChan=true; - for (UINT i=0; i<nNumChn; i++){ //check status of all other chans - if (i!=nChn && !pModDoc->IsChannelMuted(i)) { + for (CHANNELINDEX i = 0; i < nNumChn; i++) //check status of all other chans + { + if (i != nChn && !pModDoc->IsChannelMuted(i)) + { nChnIsOnlyUnMutedChan=false; //found a channel that isn't muted! break; } } - if (nChnIsOnlyUnMutedChan) { //this is the only playable channel and it is already soloed -> uunMute all + if (nChnIsOnlyUnMutedChan) // this is the only playable channel and it is already soloed -> uunMute all + { OnUnmuteAll(); return; } @@ -2183,31 +2187,32 @@ bool changed = false; CArray<UINT,UINT> validChans; - if (type==EFFECT_COLUMN || type==PARAM_COLUMN) { + if (type==EFFECT_COLUMN || type==PARAM_COLUMN) + { CArray<UINT,UINT> moreValidChans; ListChansWhereColSelected(EFFECT_COLUMN, validChans); ListChansWhereColSelected(PARAM_COLUMN, moreValidChans); //CArrayUtils<UINT>::Merge(validChans, moreValidChans); //Causes unresolved external, not sure why yet. validChans.Append(moreValidChans); //for now we'll just interpolate the same data several times. :) - } else { + } else + { ListChansWhereColSelected(type, validChans); } int nValidChans = validChans.GetCount(); //for all channels where type is selected - for (int chnIdx=0; chnIdx<nValidChans; chnIdx++) { + for (int chnIdx=0; chnIdx<nValidChans; chnIdx++) + { UINT nchn = validChans[chnIdx]; UINT row0 = GetSelectionStartRow(); UINT row1 = GetSelectionEndRow(); - if (!IsInterpolationPossible(row0, row1, nchn, type, pSndFile)) { + if (!IsInterpolationPossible(row0, row1, nchn, type, pSndFile)) continue; //skip chans where interpolation isn't possible - } - if (!changed) { //ensure we save undo buffer only before any channels are interpolated + if (!changed) //ensure we save undo buffer only before any channels are interpolated PrepareUndo(m_dwBeginSel, m_dwEndSel); - } bool doPCinterpolation = false; @@ -2220,7 +2225,8 @@ MODCOMMAND::NOTE PCnote = 0; uint16 PCinst = 0, PCparam = 0; - switch(type) { + switch(type) + { case NOTE_COLUMN: vsrc = srcCmd.note; vdest = destCmd.note; @@ -2232,6 +2238,14 @@ vdest = destCmd.vol; vcmd = srcCmd.volcmd; verr = (distance * 63) / 128; + if(srcCmd.volcmd == VOLCMD_NONE) + { + vsrc = vdest; + vcmd = destCmd.volcmd; + } else if(destCmd.volcmd == VOLCMD_NONE) + { + vdest = vsrc; + } break; case PARAM_COLUMN: case EFFECT_COLUMN: @@ -2252,6 +2266,14 @@ vsrc = srcCmd.param; vdest = destCmd.param; vcmd = srcCmd.command; + if(srcCmd.command == CMD_NONE) + { + vsrc = vdest; + vcmd = destCmd.command; + } else if(destCmd.command == CMD_NONE) + { + vdest = vsrc; + } } verr = (distance * 63) / 128; break; @@ -3128,6 +3150,7 @@ const bool bLiveRecord = IsLiveRecord(*pModDoc, *pSndFile); ModCommandPos editpos = GetEditPos(*pSndFile, bLiveRecord); MODCOMMAND* p = GetModCommand(*pSndFile, editpos); + pModDoc->GetPatternUndo()->PrepareUndo(editpos.nPat, editpos.nChn, editpos.nRow, editpos.nChn, editpos.nRow); p->Set(NOTE_PCS, mappedIndex, static_cast<uint16>(paramIndex), static_cast<uint16>((paramValue * MODCOMMAND::maxColumnValue)/127)); if(bLiveRecord == false) InvalidateRow(editpos.nRow); @@ -5185,12 +5208,12 @@ //--------------------------------------------------- -bool CViewPattern::IsInterpolationPossible(UINT startRow, UINT endRow, - UINT chan, PatternColumns colType, CSoundFile* pSndFile) { -//--------------------------------------------------------------------------------------- - if (startRow == endRow) { +bool CViewPattern::IsInterpolationPossible(ROWINDEX startRow, ROWINDEX endRow, CHANNELINDEX chan, + PatternColumns colType, CSoundFile* pSndFile) +//-------------------------------------------------------------------------------------- +{ + if (startRow == endRow) return false; - } bool result = false; const MODCOMMAND startRowMC = *pSndFile->Patterns[m_nPattern].GetpModCommand(startRow, chan); @@ -5200,21 +5223,22 @@ if(colType == EFFECT_COLUMN && (startRowMC.IsPcNote() || endRowMC.IsPcNote())) return true; - switch (colType) { + switch (colType) + { case NOTE_COLUMN: startRowCmd = startRowMC.note; endRowCmd = endRowMC.note; - result = (startRowCmd>0 && endRowCmd>0); + result = (startRowCmd >= NOTE_MIN && endRowCmd >= NOTE_MIN); break; case EFFECT_COLUMN: startRowCmd = startRowMC.command; endRowCmd = endRowMC.command; - result = (startRowCmd == endRowCmd) && (startRowCmd>0 && endRowCmd>0); + result = (startRowCmd == endRowCmd && startRowCmd != CMD_NONE) || (startRowCmd != CMD_NONE && endRowCmd == CMD_NONE) || (startRowCmd == CMD_NONE && endRowCmd != CMD_NONE); break; case VOL_COLUMN: startRowCmd = startRowMC.volcmd; endRowCmd = endRowMC.volcmd; - result = (startRowCmd == endRowCmd) && (startRowCmd>0 && endRowCmd>0); + result = (startRowCmd == endRowCmd && startRowCmd != VOLCMD_NONE) || (startRowCmd != VOLCMD_NONE && endRowCmd == VOLCMD_NONE) || (startRowCmd == VOLCMD_NONE && endRowCmd != VOLCMD_NONE); break; default: result = false; Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/View_pat.h 2010-06-05 13:13:51 UTC (rev 616) @@ -346,7 +346,7 @@ static CHANNELINDEX GetChanFromCursor(DWORD cursor); static UINT GetColTypeFromCursor(DWORD cursor); - bool IsInterpolationPossible(UINT startRow, UINT endRow, UINT chan, PatternColumns colType, CSoundFile* pSndFile); + bool IsInterpolationPossible(ROWINDEX startRow, ROWINDEX endRow, CHANNELINDEX chan, PatternColumns colType, CSoundFile* pSndFile); void Interpolate(PatternColumns type); // Return true if recording live (i.e. editing while following playback). Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/mptrack.rc 2010-06-05 13:13:51 UTC (rev 616) @@ -294,24 +294,24 @@ GROUPBOX "Render",IDC_STATIC,6,6,192,114 COMBOBOX IDC_COMBO1,18,18,54,82,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO2,78,18,73,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Change Player Options",IDC_PLAYEROPTIONS,18,36,81,14,BS_CENTER - CONTROL "Normalize Output (experimental)",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,84,168,12 - CONTROL "High quality resampling",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,112,36,84,10 - CONTROL "Slow render (for Kontakt+DFD)",IDC_GIVEPLUGSIDLETIME, + PUSHBUTTON "Change Player &Options",IDC_PLAYEROPTIONS,18,36,81,14,BS_CENTER + CONTROL "&Normalize Output (experimental)",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,84,168,12 + CONTROL "&High quality resampling",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,112,36,84,10 + CONTROL "Slow &render (for Kontakt+DFD)",IDC_GIVEPLUGSIDLETIME, "Button",BS_AUTOCHECKBOX | BS_LEFT | BS_MULTILINE | WS_TABSTOP,18,97,168,12 GROUPBOX "Limit",IDC_STATIC,6,126,192,90 - CONTROL "Limit file size to: (KBytes)",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,138,111,11 + CONTROL "Limit file &size to: (KBytes)",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,138,111,11 EDITTEXT IDC_EDIT1,138,138,50,12,ES_AUTOHSCROLL - CONTROL "Limit song length to: (seconds)",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,158,111,10 + CONTROL "Limit song &length to: (seconds)",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,158,111,10 EDITTEXT IDC_EDIT2,138,157,50,12,ES_AUTOHSCROLL LTEXT "Play:",IDC_STATIC,18,174,37,8 - CONTROL "Entire song",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,18,186,104,10 - CONTROL "From position",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,18,199,58,10 + CONTROL "&Entire song",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,18,186,104,10 + CONTROL "From &position",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,18,199,58,10 EDITTEXT IDC_EDIT3,78,198,24,12,ES_AUTOHSCROLL | ES_NUMBER CTEXT "to",IDC_STATIC,105,200,8,8 EDITTEXT IDC_EDIT4,117,198,24,12,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Channel mode (one file per channel)",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,54,168,12 - CONTROL "Instrument mode (one file per instrument)",IDC_CHECK6, + CONTROL "&Channel mode (one file per channel)",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,54,168,12 + CONTROL "&Instrument mode (one file per instrument)",IDC_CHECK6, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,66,168,12 END @@ -1876,10 +1876,10 @@ MENUITEM "&Close", ID_FILE_CLOSE MENUITEM "&Save\tCtrl+S", ID_FILE_SAVE MENUITEM "Save &As...", ID_FILE_SAVE_AS - MENUITEM "Save as &Wave...", ID_FILE_SAVEASWAVE - MENUITEM "Save as M&P3...", ID_FILE_SAVEASMP3 + MENUITEM "Export &unraped...", ID_FILE_SAVECOMPAT + MENUITEM "Export as &Wave...", ID_FILE_SAVEASWAVE + MENUITEM "Export as M&P3...", ID_FILE_SAVEASMP3 MENUITEM "Export as M&IDI...", ID_FILE_SAVEMIDI - MENUITEM "Export &unraped...", ID_FILE_SAVECOMPAT MENUITEM SEPARATOR MENUITEM "Import &MIDI Library...", ID_IMPORT_MIDILIB MENUITEM "Add Sound &Bank...", ID_ADD_SOUNDBANK @@ -2380,6 +2380,11 @@ IDS_SOUNDTOUCH_LOADFAILURE "Unable to load OpenMPT_soundtouch_i16.dll." END +STRINGTABLE +BEGIN + ID_PANIC "Kill all VSTi and sample voices\nStop all hanging VSTi and sample voices" +END + #endif // Englisch (USA) resources ///////////////////////////////////////////////////////////////////////////// Modified: trunk/OpenMPT/mptrack/res/MAINBAR.BMP =================================================================== (Binary files differ) Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/mptrack/resource.h 2010-06-05 13:13:51 UTC (rev 616) @@ -1208,6 +1208,7 @@ #define ID_PATTERN_EDIT_PCNOTE_PLUGIN 60448 #define ID_ENVELOPE_ZOOM_IN 60449 #define ID_ENVELOPE_ZOOM_OUT 60450 +#define ID_PANIC 60451 // Next default values for new objects // @@ -1215,7 +1216,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 526 -#define _APS_NEXT_COMMAND_VALUE 60451 +#define _APS_NEXT_COMMAND_VALUE 60452 #define _APS_NEXT_CONTROL_VALUE 2428 #define _APS_NEXT_SYMED_VALUE 901 #endif Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-06-05 12:45:27 UTC (rev 615) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-06-05 13:13:51 UTC (rev 616) @@ -382,7 +382,7 @@ insfile[iSmp] += ((DWORD)(BYTE)s[0x0D]) << 20; if (insfile[iSmp] > dwMemLength) insfile[iSmp] &= 0xFFFF; - if(Samples[iSmp].nLoopEnd <= 4) + if(Samples[iSmp].nLoopEnd < 2) Samples[iSmp].nLoopStart = Samples[iSmp].nLoopEnd = 0; if ((Samples[iSmp].nLoopStart >= Samples[iSmp].nLoopEnd) || (Samples[iSmp].nLoopEnd - Samples[iSmp].nLoopStart < 1)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-06-06 12:40:24
|
Revision: 617 http://modplug.svn.sourceforge.net/modplug/?rev=617&view=rev Author: saga-games Date: 2010-06-06 12:40:17 +0000 (Sun, 06 Jun 2010) Log Message: ----------- [Imp] Note Properties: Show the real finetune values for E5x in MOD/XM and E2x in S3M. [Fix] The Pattern Loop command did not work properly for rows > 255. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-06-05 13:13:51 UTC (rev 616) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-06-06 12:40:17 UTC (rev 617) @@ -16,6 +16,8 @@ #include "modsmp_ctrl.h" #include "CleanupSong.h" +extern WORD S3MFineTuneTable[16]; + #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE @@ -2118,7 +2120,7 @@ {CMD_MODCMDEX, 0xF0,0x20, 0, MOD_TYPE_MODXM, "Fine porta down"}, {CMD_MODCMDEX, 0xF0,0x30, 0, MOD_TYPE_MODXM, "Glissando Control"}, {CMD_MODCMDEX, 0xF0,0x40, 0, MOD_TYPE_MODXM, "Vibrato waveform"}, - {CMD_MODCMDEX, 0xF0,0x50, 0, MOD_TYPE_MOD, "Set finetune"}, + {CMD_MODCMDEX, 0xF0,0x50, 0, MOD_TYPE_MODXM, "Set finetune"}, {CMD_MODCMDEX, 0xF0,0x60, 0, MOD_TYPE_MODXM, "Pattern loop"}, {CMD_MODCMDEX, 0xF0,0x70, 0, MOD_TYPE_MODXM, "Tremolo waveform"}, {CMD_MODCMDEX, 0xF0,0x80, 0, MOD_TYPE_MODXM, "Set panning"}, @@ -2803,7 +2805,10 @@ strcpy(s, "smooth"); else strcpy(s, "semitones"); - break; + break; + case 0x20: // set finetune + wsprintf(s, "%dHz", S3MFineTuneTable[param & 0x0F]); + break; case 0x30: // vibrato waveform case 0x40: // tremolo waveform case 0x50: // panbrello waveform @@ -2884,6 +2889,13 @@ case 0x07: case 0x0F: strcpy(s, "square wave (cont.)"); break; } break; + case 0x50: // set finetune + { + int8 nFinetune = (param & 0x0F) << 4; + if(m_SndFile.GetType() & MOD_TYPE_XM) nFinetune += 128; + wsprintf(s, "%d", nFinetune); + } + break; case 0x60: // pattern loop if((param & 0x0F) == 0x00) strcpy(s, "loop start"); Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-06-05 13:13:51 UTC (rev 616) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-06-06 12:40:17 UTC (rev 617) @@ -223,7 +223,8 @@ BYTE nCutOff, nResonance; int nRetrigCount, nRetrigParam; BYTE nTremorCount, nTremorParam; - BYTE nPatternLoop, nPatternLoopCount; + ROWINDEX nPatternLoop; + BYTE nPatternLoopCount; BYTE nRowNote, nRowInstr; BYTE nRowVolCmd, nRowVolume; BYTE nRowCommand, nRowParam; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-06-09 19:44:52
|
Revision: 619 http://modplug.svn.sourceforge.net/modplug/?rev=619&view=rev Author: saga-games Date: 2010-06-09 19:44:45 +0000 (Wed, 09 Jun 2010) Log Message: ----------- [Imp] Song Length Estimation: Also taking the weird E60 bug into account here... (though this is still not very precise). [Ref] Song Length Estimation: Using vectors instead of large fixed-size arrays. [Imp] Treeview: Ask for confirmation when deleting things [Mod] Paste code: Changing the IsEmpty call back to old behaviour. It doesn't seem to make a difference, but let's better be safe than sorry. Modified Paths: -------------- trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-06-06 16:33:09 UTC (rev 618) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-06-09 19:44:45 UTC (rev 619) @@ -1399,7 +1399,7 @@ // if the original modcommand was empty as otherwise the unchanged parts // of the old modcommand would falsely be interpreted being of type // origFormat and ConvertCommand could change them. - if (origFormat != m_SndFile.m_nType && (doMixPaste == false || origModCmd.IsEmpty())) + if (origFormat != m_SndFile.m_nType && (doMixPaste == false || origModCmd.IsEmpty(false))) m_SndFile.ConvertCommand(&(m[col]), origFormat, m_SndFile.m_nType); } Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2010-06-06 16:33:09 UTC (rev 618) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2010-06-09 19:44:45 UTC (rev 619) @@ -1393,6 +1393,7 @@ const uint64 modItem = GetModItem(hItem); const uint32 modItemType = GetModItemType(modItem); const uint32 modItemID = GetModItemID(modItem); + TCHAR s[64]; PMODTREEDOCINFO pInfo = DocInfo[m_nDocNdx]; CModDoc *pModDoc = (pInfo) ? pInfo->pModDoc : nullptr; @@ -1402,12 +1403,16 @@ case MODITEM_SEQUENCE: if (pModDoc && pSndFile) { + wsprintf(s, _T("Delete sequence %d?"), modItemID & 0xFFFF); + if(MessageBox(s, _T("Confirmation"), MB_YESNO | MB_DEFBUTTON2) == IDNO) break; pSndFile->Order.RemoveSequence((SEQUENCEINDEX)(modItemID & 0xFFFF)); pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); } break; case MODITEM_ORDER: + wsprintf(s, _T("Delete order %d?"), modItemID & 0xFFFF); + if(MessageBox(s, _T("Confirmation"), MB_YESNO | MB_DEFBUTTON2) == IDNO) break; if ((pModDoc) && (pModDoc->RemoveOrder((SEQUENCEINDEX)(modItemID >> 16), (ORDERINDEX)(modItemID & 0xFFFF)))) { pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); @@ -1415,25 +1420,28 @@ break; case MODITEM_PATTERN: + wsprintf(s, _T("Delete pattern %d?"), modItemID & 0xFFFF); + if(MessageBox(s, _T("Confirmation"), MB_YESNO | MB_DEFBUTTON2) == IDNO) break; if ((pModDoc) && (pModDoc->RemovePattern((PATTERNINDEX)modItemID))) { - //pModDoc->UpdateAllViews(NULL, (dwItem << 16)|HINT_PATTERNDATA|HINT_PATNAMES); pModDoc->UpdateAllViews(NULL, (UINT(modItemID) << HINT_SHIFT_PAT) | HINT_PATTERNDATA|HINT_PATNAMES); } break; case MODITEM_SAMPLE: + wsprintf(s, _T("Delete sample %d?"), modItemID & 0xFFFF); + if(MessageBox(s, _T("Confirmation"), MB_YESNO | MB_DEFBUTTON2) == IDNO) break; if ((pModDoc) && (pModDoc->RemoveSample((SAMPLEINDEX)modItemID))) { - //pModDoc->UpdateAllViews(NULL, (dwItem << 16) | HINT_SMPNAMES|HINT_SAMPLEDATA|HINT_SAMPLEINFO); pModDoc->UpdateAllViews(NULL, (UINT(modItemID) << HINT_SHIFT_SMP) | HINT_SMPNAMES|HINT_SAMPLEDATA|HINT_SAMPLEINFO); } break; case MODITEM_INSTRUMENT: + wsprintf(s, _T("Delete instrument %d?"), modItemID & 0xFFFF); + if(MessageBox(s, _T("Confirmation"), MB_YESNO | MB_DEFBUTTON2) == IDNO) break; if ((pModDoc) && (pModDoc->RemoveInstrument((INSTRUMENTINDEX)modItemID))) { - //pModDoc->UpdateAllViews(NULL, (dwItem << 16)|HINT_MODTYPE|HINT_ENVELOPE|HINT_INSTRUMENT); pModDoc->UpdateAllViews(NULL, (UINT(modItemID) << HINT_SHIFT_INS) | HINT_MODTYPE|HINT_ENVELOPE|HINT_INSTRUMENT); } break; Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-06 16:33:09 UTC (rev 618) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-09 19:44:45 UTC (rev 619) @@ -89,29 +89,30 @@ // -> DESC="alternative BPM/Speed interpretation method" // UINT dwElapsedTime=0, nRow=0, nCurrentPattern=0, nNextPattern=0, nPattern=Order[0]; ROWINDEX nRow = 0; + ROWINDEX nNextPatStartRow = 0; // FT2 E60 bug ORDERINDEX nCurrentPattern = 0; ORDERINDEX nNextPattern = 0; PATTERNINDEX nPattern = Order[0]; double dElapsedTime=0.0; // -! NEW_FEATURE#0022 - UINT nMusicSpeed=m_nDefaultSpeed, nMusicTempo=m_nDefaultTempo, nNextRow=0; + UINT nMusicSpeed = m_nDefaultSpeed, nMusicTempo = m_nDefaultTempo, nNextRow = 0; UINT nMaxRow = 0, nMaxPattern = 0; LONG nGlbVol = m_nDefaultGlobalVolume, nOldGlbVolSlide = 0; - BYTE samples[MAX_CHANNELS]; - BYTE instr[MAX_CHANNELS]; - UINT notes[MAX_CHANNELS]; - BYTE vols[MAX_CHANNELS]; - BYTE oldparam[MAX_CHANNELS]; - UINT chnvols[MAX_CHANNELS]; - double patloop[MAX_CHANNELS]; + vector<BYTE> instr; + vector<UINT> notes; + vector<BYTE> vols; + vector<BYTE> oldparam; + vector<UINT> chnvols; + vector<double> patloop; + vector<ROWINDEX> patloopstart; - memset(instr, 0, sizeof(instr)); - memset(notes, 0, sizeof(notes)); - memset(vols, 0xFF, sizeof(vols)); - memset(patloop, 0, sizeof(patloop)); - memset(oldparam, 0, sizeof(oldparam)); - memset(chnvols, 64, sizeof(chnvols)); - memset(samples, 0, sizeof(samples)); + notes.resize(m_nChannels, 0); + instr.resize(m_nChannels, 0); + vols.resize(m_nChannels, 0xFF); + oldparam.resize(m_nChannels, 0); + chnvols.resize(m_nChannels, 64); + patloop.resize(m_nChannels, 0); + patloopstart.resize(m_nChannels, 0); for(CHANNELINDEX icv = 0; icv < m_nChannels; icv++) chnvols[icv] = ChnSettings[icv].nVolume; nMaxRow = m_nNextRow; nMaxPattern = m_nNextPattern; @@ -183,6 +184,8 @@ { nNextPattern = nCurrentPattern + 1; nNextRow = 0; + if(IsCompatibleMode(TRK_FASTTRACKER2)) nNextRow = nNextPatStartRow; // FT2 E60 bug + nNextPatStartRow = 0; } if (!nRow) { @@ -221,6 +224,7 @@ case CMD_POSITIONJUMP: positionJumpOnThisRow=true; nNextPattern = (ORDERINDEX)param; + nNextPatStartRow = 0; // FT2 E60 bug // see http://lpchip.com/modplug/viewtopic.php?t=2769 - FastTracker resets Dxx if Bxx is called _after_ Dxx if(!patternBreakOnThisRow || (GetType() == MOD_TYPE_XM)) nNextRow = 0; @@ -233,9 +237,10 @@ break; // Pattern Break case CMD_PATTERNBREAK: - patternBreakOnThisRow=true; + patternBreakOnThisRow = true; //Try to check next row for XPARAM nextRow = nullptr; + nNextPatStartRow = 0; // FT2 E60 bug if (nRow < Patterns[nPattern].GetNumRows() - 1) { nextRow = Patterns[nPattern] + (nRow+1) * m_nChannels + nChn; @@ -268,7 +273,7 @@ break; // Set Tempo case CMD_TEMPO: - if ((bAdjust) && (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT | MOD_TYPE_MPT))) + if ((bAdjust) && (m_nType & (MOD_TYPE_S3M | MOD_TYPE_IT | MOD_TYPE_MPT))) { if (param) pChn->nOldTempo = (BYTE)param; else param = pChn->nOldTempo; } @@ -276,10 +281,10 @@ // Tempo Slide if ((param & 0xF0) == 0x10) { - nMusicTempo += (param & 0x0F) * (nMusicSpeed-1); //rewbs.tempoSlideFix + nMusicTempo += (param & 0x0F) * (nMusicSpeed - 1); //rewbs.tempoSlideFix } else { - nMusicTempo -= (param & 0x0F) * (nMusicSpeed-1); //rewbs.tempoSlideFix + nMusicTempo -= (param & 0x0F) * (nMusicSpeed - 1); //rewbs.tempoSlideFix } // -> CODE#0010 // -> DESC="add extended parameter mechanism to pattern effects" @@ -298,8 +303,15 @@ if ((param & 0xF0) == 0xE0) nSpeedCount = (param & 0x0F) * nMusicSpeed; else if ((param & 0xF0) == 0x60) { - if (param & 0x0F) dElapsedTime += (dElapsedTime - patloop[nChn]) * (double)(param & 0x0F); - else patloop[nChn] = dElapsedTime; + if (param & 0x0F) + { + dElapsedTime += (dElapsedTime - patloop[nChn]) * (double)(param & 0x0F); + nNextPatStartRow = patloopstart[nChn]; // FT2 E60 bug + } else + { + patloop[nChn] = dElapsedTime; + patloopstart[nChn] = nRow; + } } break; case CMD_XFINEPORTAUPDOWN: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-06-12 13:17:22
|
Revision: 621 http://modplug.svn.sourceforge.net/modplug/?rev=621&view=rev Author: saga-games Date: 2010-06-12 13:17:16 +0000 (Sat, 12 Jun 2010) Log Message: ----------- [Fix] Mod Conversion: When converting to MPTM, "+++" separator patterns are not recognized as subtune indicators anymore, as that was quite annoying. [Fix] XM Saver: Completely empty patterns are loaded as empty 64-row patterns in FT2, regardless of their original size. This is now being circumvented by adding a D00 effect at the end of such patterns. [Imp] Note Properties: Set envelope position effect (Lxx in XM) is now explained properly. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/ModSequence.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-06-11 17:52:43 UTC (rev 620) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-06-12 13:17:16 UTC (rev 621) @@ -2722,6 +2722,10 @@ } break; + case CMD_SETENVPOSITION: + wsprintf(s, "Tick %d", param); + break; + case CMD_MIDI: if (param < 0x80) { @@ -2788,7 +2792,7 @@ case 0x0A: strcpy(s, "7A: Pan Env On"); break; case 0x0B: strcpy(s, "7B: Pitch Env Off"); break; case 0x0C: strcpy(s, "7C: Pitch Env On"); break; - // intentional fall-through follows + // intentional fall-through for non-MPT modules follows case 0x0D: if(m_SndFile.GetType() == MOD_TYPE_MPT) { strcpy(s, "7D: Force Pitch Env"); break; } case 0x0E: if(m_SndFile.GetType() == MOD_TYPE_MPT) { strcpy(s, "7E: Force Filter Env"); break; } default: wsprintf(s, "%02X: undefined", param); break; Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-06-11 17:52:43 UTC (rev 620) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-06-12 13:17:16 UTC (rev 621) @@ -826,6 +826,8 @@ { MODCOMMAND *p = Patterns[i]; UINT len = 0; + // Empty patterns are always loaded as 64-row patterns in FT2, regardless of their real size... + bool emptyPatNeedsFixing = (Patterns[i].GetNumRows() != 64); memset(&xmph, 0, sizeof(xmph)); xmph[0] = 9; @@ -876,6 +878,19 @@ } } } + + // no need to fix non-empty patterns + if(!p->IsEmpty()) + emptyPatNeedsFixing = false; + + // apparently, completely empty patterns are loaded as empty 64-row patterns in FT2, regardless of their original size. + // We have to avoid this, so we add a "break to row 0" command in the last row. + if(j == 1 && emptyPatNeedsFixing) + { + command = 0x0D; + param = 0; + } + if ((note) && (p->instr) && (vol > 0x0F) && (command) && (param)) { s[len++] = note; Modified: trunk/OpenMPT/soundlib/ModSequence.cpp =================================================================== --- trunk/OpenMPT/soundlib/ModSequence.cpp 2010-06-11 17:52:43 UTC (rev 620) +++ trunk/OpenMPT/soundlib/ModSequence.cpp 2010-06-12 13:17:16 UTC (rev 621) @@ -396,7 +396,7 @@ const ORDERINDEX nLengthTt = GetLengthTailTrimmed(); for(ORDERINDEX nOrd = 0; nOrd < nLengthTt; nOrd++) { - if(!m_pSndFile->Patterns.IsValidIndex(At(nOrd))) + if(!m_pSndFile->Patterns.IsValidPat(At(nOrd)) && At(nOrd) != GetIgnoreIndex()) { hasSepPatterns = true; break; @@ -414,7 +414,7 @@ for(ORDERINDEX nOrd = 0; nOrd < GetLengthTailTrimmed(); nOrd++) { // end of subsong? - if(!m_pSndFile->Patterns.IsValidIndex(At(nOrd))) + if(!m_pSndFile->Patterns.IsValidPat(At(nOrd)) && At(nOrd) != GetIgnoreIndex()) { ORDERINDEX oldLength = GetLengthTailTrimmed(); // remove all separator patterns between current and next subsong first This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-06-19 19:48:00
|
Revision: 628 http://modplug.svn.sourceforge.net/modplug/?rev=628&view=rev Author: saga-games Date: 2010-06-19 19:47:53 +0000 (Sat, 19 Jun 2010) Log Message: ----------- [Fix] Pattern Editor: New patterns were inserted in the wrong orderlist position for MOD/S3M files (before instead of after the current order). This broke in rev 616 and was supposed to be fixed in rev 622, but I somehow failed to include the patch. [Fix] (Still unfunctional) Sample Generator: There was an error in one of the preset formulas. [Imp] Instrument Editor: More helpful value display for the panning envelope in the status bar with indication what's left and what's right. [Imp] XM Saving: Panbrello is not saved anymore in compatibility mode. [Imp] Mod Conversion: When converting to XM, rogue note delays are removed from the patterns to avoid interferrence with a FT2 bug. [Ref] Some refactoring [Mod] Changed link in the release notes (history.txt -> History.txt for those case-sensitive OSes), added revision number to History.txt Revision Links: -------------- http://modplug.svn.sourceforge.net/modplug/?rev=616&view=rev http://modplug.svn.sourceforge.net/modplug/?rev=622&view=rev Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/SampleGenerator.cpp trunk/OpenMPT/mptrack/View_ins.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/packageTemplate/OMPT_1.18_ReleaseNotes.html trunk/OpenMPT/soundlib/Load_mod.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -324,11 +324,10 @@ if (dwHintMask & (HINT_MODTYPE|HINT_PATNAMES)) { UINT nPat; - if (dwHintMask&HINT_PATNAMES) { + if (dwHintMask&HINT_PATNAMES) nPat = (dwHintMask >> HINT_SHIFT_PAT); - } else { + else nPat = SendViewMessage(VIEWMSG_GETCURRENTPATTERN); - } m_pSndFile->GetPatternName(nPat, s, sizeof(s)); m_EditPatName.SetWindowText(s); BOOL bXMIT = (m_pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT)) ? TRUE : FALSE; @@ -781,11 +780,11 @@ ORDERINDEX nCurOrd = m_OrderList.GetCurSel(true).nOrdLo; PATTERNINDEX pat = pSndFile->Order[nCurOrd]; ROWINDEX rows = 64; - if ((pat < pSndFile->Patterns.Size()) && (pSndFile->Patterns[pat]) && (pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT))) + if(pSndFile->Patterns.IsValidPat(pat)) { + nCurOrd++; // only if the current oder is already occupied, create a new pattern at the next position. rows = pSndFile->Patterns[pat].GetNumRows(); rows = CLAMP(rows, pSndFile->GetModSpecifications().patternRowsMin, pSndFile->GetModSpecifications().patternRowsMax); - nCurOrd++; // only if the current oder is already occupied, create a new pattern at the next position. } PATTERNINDEX nNewPat = m_pModDoc->InsertPattern(nCurOrd, rows); if ((nNewPat != PATTERNINDEX_INVALID) && (nNewPat < pSndFile->Patterns.Size())) Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -9,7 +9,7 @@ #include "snddev.h" #include ".\mpdlgs.h" -#define str_preampChangeNote GetStrI18N(_TEXT("Note: Pre-Amp setting affects sample volume only. Changing this setting may cause undesired effects on volume balance between sample based instruments and plugin instrument.")) +#define str_preampChangeNote GetStrI18N(_TEXT("Note: Pre-Amp setting affects sample volume only. Changing this setting may cause undesired effects on volume balance between sample based instruments and plugin instruments.")) //#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" @@ -353,13 +353,7 @@ m_CbnBufferLength.GetWindowText(s, sizeof(s)); m_nBufferLength = atoi(s); //Check given value. - if(m_nBufferLength < SNDDEV_MINBUFFERLEN) - m_nBufferLength = SNDDEV_MINBUFFERLEN; - else - { - if(m_nBufferLength > SNDDEV_MAXBUFFERLEN) - m_nBufferLength = SNDDEV_MAXBUFFERLEN; - } + m_nBufferLength = CLAMP(m_nBufferLength, SNDDEV_MINBUFFERLEN, SNDDEV_MAXBUFFERLEN); wsprintf(s, "%d ms", m_nBufferLength); m_CbnBufferLength.SetWindowText(s); } Modified: trunk/OpenMPT/mptrack/SampleGenerator.cpp =================================================================== --- trunk/OpenMPT/mptrack/SampleGenerator.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/mptrack/SampleGenerator.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -601,7 +601,7 @@ presets.AddPreset(preset); preset.description = "Noisy Saw"; - preset.expression = "(x mod 800) / 800 - 0.5 + rnd (0.1)"; + preset.expression = "(x mod 800) / 800 - 0.5 + rnd(0.1)"; presets.AddPreset(preset); preset.description = "PWM Filter"; Modified: trunk/OpenMPT/mptrack/View_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_ins.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/mptrack/View_ins.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -1387,15 +1387,23 @@ if (nVal < 0) nVal = 0; if (nVal > 64) nVal = 64; if (nTick < 0) nTick = 0; - if (nTick <= EnvGetReleaseNodeTick() + 1 || EnvGetReleaseNode() == ENV_RELEASE_NODE_UNSET) { - int displayVal = (m_nEnv != ENV_VOLUME && !(m_nEnv == ENV_PITCH && (pIns->PitchEnv.dwFlags & ENV_FILTER))) ? nVal - 32 : nVal; - wsprintf(s, "Tick %d, [%d]", nTick, displayVal); - } else { + if (nTick <= EnvGetReleaseNodeTick() + 1 || EnvGetReleaseNode() == ENV_RELEASE_NODE_UNSET) + { + // ticks before release node (or no release node) + const int displayVal = (m_nEnv != ENV_VOLUME && !(m_nEnv == ENV_PITCH && (pIns->PitchEnv.dwFlags & ENV_FILTER))) ? nVal - 32 : nVal; + if(m_nEnv != ENV_PANNING) + wsprintf(s, "Tick %d, [%d]", nTick, displayVal); + else // panning envelope: display right/center/left chars + wsprintf(s, "Tick %d, [%d %c]", nTick, abs(displayVal), displayVal > 0 ? 'R' : (displayVal < 0 ? 'L' : 'C')); + } else + { + // ticks after release node int displayVal = (nVal - EnvGetReleaseNodeValue()) * 2; displayVal = (m_nEnv != ENV_VOLUME) ? displayVal - 32 : displayVal; wsprintf(s, "Tick %d, [Rel%c%d]", nTick, displayVal > 0 ? '+' : '-', abs(displayVal)); } UpdateIndicator(s); + if ((m_dwStatus & INSSTATUS_DRAGGING) && (m_nDragItem)) { BOOL bChanged = FALSE; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -777,12 +777,12 @@ //Log("dst: %d; src: %d; blk: %d\n", row, (row-offset/2), (row-1)); switch(i & 7) { - case 0: dest->note = src->note; blank->note=0; break; - case 1: dest->instr = src->instr; blank->instr=0; break; - case 2: dest->vol = src->vol; blank->vol=0; - dest->volcmd = src->volcmd; blank->volcmd=0; break; - case 3: dest->command = src->command; blank->command=0;break; - case 4: dest->param = src->param; blank->param=0; break; + case NOTE_COLUMN: dest->note = src->note; blank->note = 0; break; + case INST_COLUMN: dest->instr = src->instr; blank->instr = 0; break; + case VOL_COLUMN: dest->vol = src->vol; blank->vol = 0; + dest->volcmd = src->volcmd; blank->volcmd = 0; break; + case EFFECT_COLUMN: dest->command = src->command; blank->command = 0; break; + case PARAM_COLUMN: dest->param = src->param; blank->param = 0; break; } } } @@ -830,12 +830,12 @@ Log("dst: %d; src: %d\n", row, srcRow); switch(i & 7) { - case 0: dest->note = src->note; break; - case 1: dest->instr = src->instr; break; - case 2: dest->vol = src->vol; - dest->volcmd = src->volcmd; break; - case 3: dest->command = src->command; break; - case 4: dest->param = src->param; break; + case NOTE_COLUMN: dest->note = src->note; break; + case INST_COLUMN: dest->instr = src->instr; break; + case VOL_COLUMN: dest->vol = src->vol; + dest->volcmd = src->volcmd; break; + case EFFECT_COLUMN: dest->command = src->command; break; + case PARAM_COLUMN: dest->param = src->param; break; } } } @@ -2046,18 +2046,18 @@ MODCOMMAND *m = pSndFile->Patterns[m_nPattern] + m_nRow * pSndFile->m_nChannels + ((m_dwCursor & 0xFFFF) >> 3); switch(m_dwCursor & 7) { - case 0: - case 1: + case NOTE_COLUMN: + case INST_COLUMN: m_cmdOld.note = m->note; m_cmdOld.instr = m->instr; SendCtrlMessage(CTRLMSG_SETCURRENTINSTRUMENT, m_cmdOld.instr); break; - case 2: + case VOL_COLUMN: m_cmdOld.volcmd = m->volcmd; m_cmdOld.vol = m->vol; break; - case 3: - case 4: + case EFFECT_COLUMN: + case PARAM_COLUMN: m_cmdOld.command = m->command; m_cmdOld.param = m->param; break; @@ -2082,11 +2082,11 @@ switch(nCursor) { - case 0: p->note = m_cmdOld.note; //Note - case 1: p->instr = m_cmdOld.instr; break; //Octave - case 2: p->vol = m_cmdOld.vol; p->volcmd = m_cmdOld.volcmd; break; //Vol - case 3: //Effect - case 4: p->command = m_cmdOld.command; p->param = m_cmdOld.param; break; + case NOTE_COLUMN: p->note = m_cmdOld.note; + case INST_COLUMN: p->instr = m_cmdOld.instr; break; + case VOL_COLUMN: p->vol = m_cmdOld.vol; p->volcmd = m_cmdOld.volcmd; break; + case EFFECT_COLUMN: + case PARAM_COLUMN: p->command = m_cmdOld.command; p->param = m_cmdOld.param; break; } pModDoc->SetModified(); @@ -4424,7 +4424,7 @@ // Simply backup the whole row. pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, nChn, m_nRow, pSndFile->GetNumChannels(), 1); - PatternRow prowbase = pSndFile->Patterns[m_nPattern].GetRow(m_nRow); + const PatternRow prowbase = pSndFile->Patterns[m_nPattern].GetRow(m_nRow); MODCOMMAND* p = &prowbase[nChn]; const MODCOMMAND oldcmd = *p; // This is the command we are about to overwrite Modified: trunk/OpenMPT/packageTemplate/History.txt =================================================================== --- trunk/OpenMPT/packageTemplate/History.txt 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/packageTemplate/History.txt 2010-06-19 19:47:53 UTC (rev 628) @@ -10,8 +10,8 @@ (tx XYZ): thanks to XYZ for telling us about the bug -v1.18.02.00 (May 2010) ----------------------- +v1.18.02.00 (May 2010, revision 610) +------------------------------------ General tab [Imp] <Jojo> Disabled tempo slider for MOD files (it was just confusing) Modified: trunk/OpenMPT/packageTemplate/OMPT_1.18_ReleaseNotes.html =================================================================== --- trunk/OpenMPT/packageTemplate/OMPT_1.18_ReleaseNotes.html 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/packageTemplate/OMPT_1.18_ReleaseNotes.html 2010-06-19 19:47:53 UTC (rev 628) @@ -186,7 +186,7 @@ <h3>There's more...</h3> <p> - For a detailed description of what has changed, check <a href="history.txt">history.txt</a>. + For a detailed description of what has changed, check <a href="History.txt">History.txt</a>. </p> <h2>Known Issues</h2> Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -58,7 +58,7 @@ case '\\' - 56: command = CMD_SMOOTHMIDI; break; //rewbs.smoothVST: 36 - note: this is actually displayed as "-" in FT2, but seems to be doing nothing. //case ':' - 21: command = CMD_DELAYCUT; break; //37 case '#' + 3: command = CMD_XPARAM; break; //rewbs.XMfixes - XParam is 38 - default: command = 0; + default: command = CMD_NONE; } m->command = command; m->param = param; @@ -68,7 +68,7 @@ WORD CSoundFile::ModSaveCommand(const MODCOMMAND *m, const bool bXM, const bool bCompatibilityExport) const //--------------------------------------------------------------------------------------------------------- { - UINT command = m->command & 0x3F, param = m->param; + UINT command = m->command, param = m->param; switch(command) { @@ -77,16 +77,16 @@ case CMD_PORTAMENTOUP: if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_MPT)) { - if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x10; break; } - else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x10; break; } + if ((param & 0xF0) == 0xE0) { command = 0x0E; param = ((param & 0x0F) >> 2) | 0x10; break; } + else if ((param & 0xF0) == 0xF0) { command = 0x0E; param &= 0x0F; param |= 0x10; break; } } command = 0x01; break; case CMD_PORTAMENTODOWN: if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_IT|MOD_TYPE_STM|MOD_TYPE_MPT)) { - if ((param & 0xF0) == 0xE0) { command=0x0E; param=((param & 0x0F) >> 2)|0x20; break; } - else if ((param & 0xF0) == 0xF0) { command=0x0E; param &= 0x0F; param|=0x20; break; } + if ((param & 0xF0) == 0xE0) { command = 0x0E; param= ((param & 0x0F) >> 2) | 0x20; break; } + else if ((param & 0xF0) == 0xF0) { command = 0x0E; param &= 0x0F; param |= 0x20; break; } } command = 0x02; break; @@ -103,7 +103,7 @@ { param = min(param << 1, 0xFF); } - else if(param == 0xA4) + else if(param == 0xA4) // surround { if(bCompatibilityExport || !bXM) { @@ -135,12 +135,17 @@ case CMD_RETRIG: command = 'R' - 55; break; case CMD_TREMOR: command = 'T' - 55; break; case CMD_XFINEPORTAUPDOWN: - if(bCompatibilityExport && (param & 0xF0) > 2) + if(bCompatibilityExport && (param & 0xF0) > 2) // X1x and X2x are legit, everything above are MPT extensions, which don't belong here. command = param = 0; else command = 'X' - 55; break; - case CMD_PANBRELLO: command = 'Y' - 55; break; + case CMD_PANBRELLO: + if(bCompatibilityExport) + command = param = 0; + else + command = 'Y' - 55; + break; case CMD_MIDI: if(bCompatibilityExport) command = param = 0; @@ -153,9 +158,6 @@ else command = '\\' - 56; break; - case CMD_DELAYCUT: - command = param = 0; - break; case CMD_XPARAM: //rewbs.XMfixes - XParam is 38 if(bCompatibilityExport) command = param = 0; @@ -183,8 +185,14 @@ default: command = 0x0E; break; } break; - default: command = param = 0; + default: + command = param = 0; } + + // don't even think about saving XM effects in MODs... + if(command > 0x0F && !bXM) + command = param = 0; + return (WORD)((command << 8) | (param)); } Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -3572,13 +3572,14 @@ { MODINSTRUMENT *pIns = pChn->pModInstrument; if (((pIns->VolEnv.dwFlags & ENV_LOOP) || (m_nType & (MOD_TYPE_XM|MOD_TYPE_MT2))) && (pIns->nFadeOut)) - { + { pChn->dwFlags |= CHN_NOTEFADE; } if (pIns->VolEnv.nReleaseNode != ENV_RELEASE_NODE_UNSET) { - pChn->nVolEnvValueAtReleaseJump = getVolEnvValueFromPosition(pChn->nVolEnvPosition, pIns); pChn->nVolEnvPosition= pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode]; + pChn->nVolEnvValueAtReleaseJump = getVolEnvValueFromPosition(pChn->nVolEnvPosition, pIns); + pChn->nVolEnvPosition= pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode]; } } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-06-19 17:12:30 UTC (rev 627) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-06-19 19:47:53 UTC (rev 628) @@ -3794,10 +3794,16 @@ } } // End if (newTypeIsS3M) - ////////////////////////////////////////////////// - // Convert anything to XM - adjust volume column + //////////////////////////////////////////////////////////////////////// + // Convert anything to XM - adjust volume column, breaking EDx command if (newTypeIsXM) { + // remove EDx if no note is next to it, or it will retrigger the note in FT2 mode + if(m->command == CMD_MODCMDEX && (m->param & 0xF0) == 0xD0 && m->note == NOTE_NONE) + { + m->command = m->param = 0; + } + if(!m->command) switch(m->volcmd) { case VOLCMD_PORTADOWN: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-06-24 20:59:06
|
Revision: 631 http://modplug.svn.sourceforge.net/modplug/?rev=631&view=rev Author: saga-games Date: 2010-06-24 20:58:59 +0000 (Thu, 24 Jun 2010) Log Message: ----------- [Imp] J2B Loader: J2B files with extended instrument settings and multiple samples per instrument work properly now. Such J2B files were not used in the game but have been created by JJ2 players using MOD2J2B. Also made the code more readable + various other small changes. [Mod] OpenMPT: Version is now 1.18.02.01 Modified Paths: -------------- trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/load_j2b.cpp Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-06-22 18:15:10 UTC (rev 630) +++ trunk/OpenMPT/mptrack/version.h 2010-06-24 20:58:59 UTC (rev 631) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 #define VER_MINOR 02 -#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_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-06-22 18:15:10 UTC (rev 630) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-06-24 20:58:59 UTC (rev 631) @@ -4,7 +4,8 @@ * Purpose: Load RIFF AM and RIFF AMFF modules (Galaxy Sound System). * 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) + * RIFF AM is the newer version of the format, generally following the RIFF standard closely. + * Authors: Johannes Schultz (OpenMPT port, reverse engineering + loader implementation of the instrument format) * Chris Moeller (foo_dumb - this is almost a complete port of his code, thanks) * */ @@ -16,6 +17,38 @@ #endif // ZLIB_WINAPI #include "../zlib/zlib.h" +// 32-Bit J2B header identifiers +#define J2BHEAD_MUSE 0x4553554D +#define J2BHEAD_DEADBEAF 0xAFBEADDE +#define J2BHEAD_DEADBABE 0xBEBAADDE + +// 32-Bit chunk identifiers +#define AMCHUNKID_RIFF 0x46464952 +#define AMCHUNKID_AMFF 0x46464D41 +#define AMCHUNKID_AM__ 0x20204D41 +#define AMCHUNKID_MAIN 0x4E49414D +#define AMCHUNKID_INIT 0x54494E49 +#define AMCHUNKID_ORDR 0x5244524F +#define AMCHUNKID_PATT 0x54544150 +#define AMCHUNKID_INST 0x54534E49 +#define AMCHUNKID_SAMP 0x504D4153 +#define AMCHUNKID_AI__ 0x20204941 +#define AMCHUNKID_AS__ 0x20205341 + +// Envelope flags +#define AMENV_ENABLED 0x01 +#define AMENV_SUSTAIN 0x02 +#define AMENV_LOOP 0x04 + +// Sample flags +#define AMSMP_16BIT 0x04 +#define AMSMP_LOOP 0x08 +#define AMSMP_PINGPONG 0x10 +#define AMSMP_PANNING 0x20 +#define AMSMP_EXISTS 0x80 +// some flags are still missing... what is f.e. 0x8000? + + #pragma pack(1) // header for compressed j2b files @@ -45,18 +78,40 @@ uint8 channels; uint8 speed; uint8 tempo; - uint32 unknown; + uint32 unknown; // 0x16078035 if original file was MOD, 0xC50100FF for everything else? uint8 globalvolume; }; +// AMFF instrument envelope point +struct AMFFINST_ENVPOINT +{ + uint16 tick; + uint8 pointval; // 0...64 +}; + +// AMFF instrument header struct AMFFCHUNK_INSTRUMENT { - uint8 unknown; // 0x00 - uint8 sample; // sample number - char name[28]; - char stuff[195]; // lots of NULs? + uint8 unknown; // 0x00 + uint8 index; // actual instrument number + char name[28]; + uint8 numsamples; + uint8 samplemap[120]; + uint8 autovib_type; + uint16 autovib_sweep; + uint16 autovib_depth; + uint16 autovib_rate; + uint8 envflags; // high nibble = pan env flags, low nibble = vol env flags (both nibbles work the same way) + uint8 envnumpoints; // high nibble = pan env length, low nibble = vol env length + uint8 envsustainpoints; // you guessed it... high nibble = pan env sustain point, low nibble = vol env sustain point + uint8 envloopstarts; // i guess you know the pattern now. + uint8 envloopends; // same here. + AMFFINST_ENVPOINT volenv[10]; + AMFFINST_ENVPOINT panenv[10]; + uint16 fadeout; }; +// AMFF sample header struct AMFFCHUNK_SAMPLE { uint32 signature; // "SAMP" @@ -73,13 +128,44 @@ uint32 reserved2; }; +// AM instrument envelope point +struct AMINST_ENVPOINT +{ + uint16 tick; + uint16 pointval; +}; + +// AM instrument envelope +struct AMINST_ENVELOPE +{ + uint16 flags; + uint8 numpoints; // actually, it's num. points - 1, and 0xFF if there is no envelope + uint8 suslooppoint; + uint8 loopstart; + uint8 loopend; + AMINST_ENVPOINT values[10]; + uint16 fadeout; // why is this here? it's only needed for the volume envelope... +}; + +// AM instrument header struct AMCHUNK_INSTRUMENT { - uint8 unknown; // 0x00 - uint8 sample; // sample number - char name[32]; + uint8 unknown1; // 0x00 + uint8 index; // actual instrument number + char name[32]; + uint8 samplemap[128]; + uint8 autovib_type; + uint16 autovib_sweep; + uint16 autovib_depth; + uint16 autovib_rate; + uint8 unknown2[7]; + AMINST_ENVELOPE volenv; + AMINST_ENVELOPE pitchenv; + AMINST_ENVELOPE panenv; + uint16 numsamples; }; +// AM sample header struct AMCHUNK_SAMPLE { uint32 signature; // "SAMP" @@ -89,7 +175,7 @@ uint16 pan; uint16 volume; uint16 flags; - uint16 unkown; + uint16 unkown; // 0x0000 / 0x0080? uint32 length; uint32 loopstart; uint32 loopend; @@ -98,7 +184,10 @@ #pragma pack() -static uint8 riffam_efftrans[26] = + +// And here are some nice lookup tables! + +static uint8 riffam_efftrans[] = { CMD_ARPEGGIO, CMD_PORTAMENTOUP, CMD_PORTAMENTODOWN, CMD_TONEPORTAMENTO, CMD_VIBRATO, CMD_TONEPORTAVOL, CMD_VIBRATOVOL, CMD_TREMOLO, @@ -109,9 +198,17 @@ CMD_TREMOR, CMD_XFINEPORTAUPDOWN, }; -bool Convert_RIFF_AM_Pattern(PATTERNINDEX nPat, const LPCBYTE lpStream, DWORD dwMemLength, bool bIsAM, CSoundFile *pSndFile) -//-------------------------------------------------------------------------------------------------------------------------- + +static uint8 riffam_autovibtrans[] = { + VIB_SINE, VIB_SQUARE, VIB_RAMP_UP, VIB_RAMP_DOWN, VIB_RANDOM, +}; + + +// Convert RIFF AM(FF) pattern data to MPT pattern data. +bool Convert_RIFF_AM_Pattern(const PATTERNINDEX nPat, const LPCBYTE lpStream, const DWORD dwMemLength, const bool bIsAM, CSoundFile *pSndFile) +//-------------------------------------------------------------------------------------------------------------------------------------------- +{ // version false = AMFF, true = AM #define ASSERT_CAN_READ(x) \ if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; @@ -134,12 +231,11 @@ MODCOMMAND *mrow = pSndFile->Patterns[nPat]; MODCOMMAND *m = mrow; ROWINDEX nRow = 0; - uint8 flags; while((nRow < nRows) && (dwMemPos < dwMemLength)) { ASSERT_CAN_READ(1); - flags = lpStream[dwMemPos]; + const uint8 flags = lpStream[dwMemPos]; dwMemPos++; if (flags == 0) { @@ -159,7 +255,7 @@ m->param = lpStream[dwMemPos]; dwMemPos += 2; - if(m->command <= 25) + if(m->command < ARRAYELEMCOUNT(riffam_efftrans)) { // command translation m->command = riffam_efftrans[m->command]; @@ -170,6 +266,15 @@ case CMD_ARPEGGIO: if(m->param == 0) m->command = CMD_NONE; break; + case CMD_VOLUME: + if(m->volcmd == VOLCMD_NONE) + { + m->volcmd = VOLCMD_VOLUME; + m->vol = CLAMP(m->param, 0, 64); + m->command = CMD_NONE; + m->param = 0; + } + break; case CMD_TONEPORTAVOL: case CMD_VIBRATOVOL: case CMD_VOLUMESLIDE: @@ -185,7 +290,7 @@ m->param = ((m->param >> 4) * 10) + (m->param & 0x0F); break; case CMD_MODCMDEX: - pSndFile->MODExx2S3MSxx(m); + CSoundFile::MODExx2S3MSxx(m); break; case CMD_TEMPO: if(m->param <= 0x1F) m->command = CMD_SPEED; @@ -221,7 +326,8 @@ ASSERT_CAN_READ(2); m->instr = lpStream[dwMemPos]; m->note = lpStream[dwMemPos + 1]; - if(m->note > NOTE_MAX) m->note = NOTE_NOTECUT; + if(m->note == 0x80) m->note = NOTE_KEYOFF; + else if(m->note > 0x80) m->note = NOTE_FADE; // I guess the support for IT "note fade" notes was not intended in mod2j2b, but hey, it works! :-D dwMemPos += 2; } @@ -243,8 +349,99 @@ #undef ASSERT_CAN_READ } + +// Convert envelope data from a RIFF AMFF module (old format) to MPT envelope data. +void Convert_RIFF_AMFF_Envelope(const uint8 flags, const uint8 numpoints, const uint8 sustainpoint, const uint8 loopstart, const uint8 loopend, const AMFFINST_ENVPOINT *envelope, INSTRUMENTENVELOPE *pMPTEnv) +//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +{ + if(envelope == nullptr || pMPTEnv == nullptr) + return; + + pMPTEnv->dwFlags = (flags & AMENV_ENABLED) ? ENV_ENABLED : 0; + if(flags & AMENV_SUSTAIN) pMPTEnv->dwFlags |= ENV_SUSTAIN; + if(flags & AMENV_LOOP) pMPTEnv->dwFlags |= ENV_LOOP; + + pMPTEnv->nReleaseNode = ENV_RELEASE_NODE_UNSET; + pMPTEnv->nNodes = min(numpoints, 10); // the buggy mod2j2b converter will actually NOT limit this to 10 points if the envelope is longer. + + pMPTEnv->nSustainStart = pMPTEnv->nSustainEnd = sustainpoint; + if(pMPTEnv->nSustainStart > pMPTEnv->nNodes) + pMPTEnv->dwFlags &= ~ENV_SUSTAIN; + + pMPTEnv->nLoopStart = loopstart; + pMPTEnv->nLoopEnd = loopend; + if(pMPTEnv->nLoopStart > pMPTEnv->nLoopEnd || pMPTEnv->nLoopStart > pMPTEnv->nNodes) + pMPTEnv->dwFlags &= ~ENV_LOOP; + + for(size_t i = 0; i < 10; i++) + { + pMPTEnv->Ticks[i] = LittleEndianW(envelope[i].tick) >> 4; + if(i == 0) + pMPTEnv->Ticks[0] = 0; + else if(pMPTEnv->Ticks[i] < pMPTEnv->Ticks[i - 1]) + pMPTEnv->Ticks[i] = pMPTEnv->Ticks[i - 1] + 1; + + pMPTEnv->Values[i] = CLAMP(envelope[i].pointval, 0, 0x40); + } + +} + + +// Convert envelope data from a RIFF AM module (new format) to MPT envelope data. +void Convert_RIFF_AM_Envelope(const AMINST_ENVELOPE *pAMEnv, INSTRUMENTENVELOPE *pMPTEnv, const enmEnvelopeTypes env) +//------------------------------------------------------------------------------------------------------------------- +{ + if(pAMEnv == nullptr || pMPTEnv == nullptr) + return; + + if(pAMEnv->numpoints == 0xFF || pAMEnv->numpoints == 0x00) + return; + + uint16 flags = LittleEndianW(pAMEnv->flags); + pMPTEnv->dwFlags = (flags & AMENV_ENABLED) ? ENV_ENABLED : 0; + if(flags & AMENV_SUSTAIN) pMPTEnv->dwFlags |= ENV_SUSTAIN; + if(flags & AMENV_LOOP) pMPTEnv->dwFlags |= ENV_LOOP; + + pMPTEnv->nReleaseNode = ENV_RELEASE_NODE_UNSET; + pMPTEnv->nNodes = min(pAMEnv->numpoints + 1, 10); + + pMPTEnv->nSustainStart = pMPTEnv->nSustainEnd = pAMEnv->suslooppoint; + if(pMPTEnv->nSustainStart > pMPTEnv->nNodes) + pMPTEnv->dwFlags &= ~ENV_SUSTAIN; + + pMPTEnv->nLoopStart = pAMEnv->loopstart; + pMPTEnv->nLoopEnd = pAMEnv->loopend; + if(pMPTEnv->nLoopStart > pMPTEnv->nLoopEnd || pMPTEnv->nLoopStart > pMPTEnv->nNodes) + pMPTEnv->dwFlags &= ~ENV_LOOP; + + for(size_t i = 0; i < 10; i++) + { + pMPTEnv->Ticks[i] = LittleEndianW(pAMEnv->values[i].tick >> 4); + if(i == 0) + pMPTEnv->Ticks[i] = 0; + else if(pMPTEnv->Ticks[i] < pMPTEnv->Ticks[i - 1]) + pMPTEnv->Ticks[i] = pMPTEnv->Ticks[i - 1] + 1; + + const uint16 val = LittleEndianW(pAMEnv->values[i].pointval); + switch(env) + { + case ENV_VOLUME: // 0....32767 + pMPTEnv->Values[i] = (BYTE)((val + 1) >> 9); + break; + case ENV_PITCH: // -4096....4096 + pMPTEnv->Values[i] = (BYTE)((((int16)val) + 0x1001) >> 7); + break; + case ENV_PANNING: // -32768...32767 + pMPTEnv->Values[i] = (BYTE)((((int16)val) + 0x8001) >> 10); + break; + } + pMPTEnv->Values[i] = CLAMP(pMPTEnv->Values[i], ENVELOPE_MIN, ENVELOPE_MAX); + } +} + + bool CSoundFile::ReadAM(const LPCBYTE lpStream, const DWORD dwMemLength) -//------------------------------------------------------------------------ +//---------------------------------------------------------------------- { #define ASSERT_CAN_READ(x) \ if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; @@ -256,7 +453,7 @@ ASSERT_CAN_READ(sizeof(AMFF_RIFFCHUNK)); AMFF_RIFFCHUNK *chunkheader = (AMFF_RIFFCHUNK *)lpStream; - if(LittleEndian(chunkheader->signature) != 0x46464952 // "RIFF" + if(LittleEndian(chunkheader->signature) != AMCHUNKID_RIFF // "RIFF" || LittleEndian(chunkheader->chunksize) != dwMemLength - sizeof(AMFF_RIFFCHUNK) ) return false; @@ -265,8 +462,8 @@ bool bIsAM; // false: AMFF, true: AM ASSERT_CAN_READ(4); - if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) == 0x46464D41) bIsAM = false; // "AMFF" - else if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) == 0x20204D41) bIsAM = true; // "AM " + if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) == AMCHUNKID_AMFF) bIsAM = false; // "AMFF" + else if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) == AMCHUNKID_AM__) bIsAM = true; // "AM " else return false; dwMemPos += 4; m_nChannels = 0; @@ -279,12 +476,12 @@ dwMemPos += sizeof(AMFF_RIFFCHUNK); ASSERT_CAN_READ(LittleEndian(chunkheader->chunksize)); - DWORD dwChunkEnd = dwMemPos + LittleEndian(chunkheader->chunksize); + const DWORD dwChunkEnd = dwMemPos + LittleEndian(chunkheader->chunksize); switch(LittleEndian(chunkheader->signature)) { - case 0x4E49414D: // "MAIN" - Song info (AMFF) - case 0x54494E49: // "INIT" - Song info (AM) + case AMCHUNKID_MAIN: // "MAIN" - Song info (AMFF) + case AMCHUNKID_INIT: // "INIT" - Song info (AM) if((LittleEndian(chunkheader->signature) == 0x4E49414D && !bIsAM) || (LittleEndian(chunkheader->signature) == 0x54494E49 && bIsAM)) { ASSERT_CAN_READ_CHUNK(sizeof(AMFFCHUNK_MAIN)); @@ -304,6 +501,7 @@ m_nDefaultGlobalVolume = mainchunk->globalvolume << 1; m_nSamplePreAmp = m_nVSTiVolume = 48; m_nType = MOD_TYPE_IT; + ASSERT(LittleEndian(mainchunk->unknown) == 0xFF0001C5 || LittleEndian(mainchunk->unknown) == 0x35800716); // It seems like there's no way to differentiate between // Muted and Surround channels (they're all 0xA0) - might @@ -330,132 +528,237 @@ } break; - case 0x5244524F: // "ORDR" - Order list + case AMCHUNKID_ORDR: // "ORDR" - Order list ASSERT_CAN_READ_CHUNK(1); Order.ReadAsByte(&lpStream[dwMemPos + 1], lpStream[dwMemPos] + 1, dwChunkEnd - (dwMemPos + 1)); break; - case 0x54544150: // "PATT" - Pattern data for one pattern + case AMCHUNKID_PATT: // "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, this); break; - case 0x54534E49: // "INST" - Instrument (only in RIFF AMFF) + case AMCHUNKID_INST: // "INST" - Instrument (only in RIFF AMFF) if(!bIsAM) { ASSERT_CAN_READ_CHUNK(sizeof(AMFFCHUNK_INSTRUMENT)); - AMFFCHUNK_INSTRUMENT *inschunk = (AMFFCHUNK_INSTRUMENT *)(lpStream + dwMemPos); + AMFFCHUNK_INSTRUMENT *instheader = (AMFFCHUNK_INSTRUMENT *)(lpStream + dwMemPos); dwMemPos += sizeof(AMFFCHUNK_INSTRUMENT); - SAMPLEINDEX nSmp = inschunk->sample + 1; - if(nSmp >= MAX_SAMPLES) + const INSTRUMENTINDEX nIns = instheader->index + 1; + if(nIns >= MAX_INSTRUMENTS) break; - m_nSamples = max(m_nSamples, nSmp); - memcpy(m_szNames[nSmp], inschunk->name, 28); - SpaceToNullStringFixed(m_szNames[nSmp], 28); + if(Instruments[nIns] != nullptr) + delete Instruments[nIns]; - ASSERT_CAN_READ_CHUNK(sizeof(AMFFCHUNK_SAMPLE)); - AMFFCHUNK_SAMPLE *smpchunk = (AMFFCHUNK_SAMPLE *)(lpStream + dwMemPos); - dwMemPos += sizeof(AMFFCHUNK_SAMPLE); + MODINSTRUMENT *pIns = new MODINSTRUMENT; + if(pIns == nullptr) + break; + Instruments[nIns] = pIns; + MemsetZero(*pIns); + SetDefaultInstrumentValues(pIns); - if(smpchunk->signature != 0x504D4153) break; // SAMP + m_nInstruments = max(m_nInstruments, nIns); - memcpy(m_szNames[nSmp], smpchunk->name, 28); - SpaceToNullStringFixed(m_szNames[nSmp], 28); - - Samples[nSmp].nPan = smpchunk->pan << 2; - Samples[nSmp].nVolume = smpchunk->volume << 2; - Samples[nSmp].nGlobalVol = 64; - Samples[nSmp].nLength = LittleEndian(smpchunk->length); - Samples[nSmp].nLoopStart = LittleEndian(smpchunk->loopstart); - Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend); - Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate); + memcpy(pIns->name, instheader->name, 28); + SpaceToNullStringFixed(pIns->name, 28); - uint16 flags = LittleEndianW(smpchunk->flags); - if(flags & 0x04) - Samples[nSmp].uFlags |= CHN_16BIT; - if(flags & 0x08) - Samples[nSmp].uFlags |= CHN_LOOP; - if(flags & 0x10) - Samples[nSmp].uFlags |= CHN_PINGPONGLOOP; - if(flags & 0x20) - Samples[nSmp].uFlags |= CHN_PANNING; + for(BYTE i = 0; i < 128; i++) + { + pIns->NoteMap[i] = i + 1; + pIns->Keyboard[i] = instheader->samplemap[i] + m_nSamples + 1; + } - dwMemPos += ReadSample(&Samples[nSmp], (flags & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); + pIns->nGlobalVol = 64; + pIns->nPan = 128; + pIns->nFadeOut = LittleEndianW(instheader->fadeout) << 5; + pIns->nPPC = NOTE_MIDDLEC - 1; + + // interleaved envelope data... meh. gotta split it up here and decode it separately. + // note: mod2j2b is BUGGY and always writes ($original_num_points & 0x0F) in the header, + // but just has room for 10 envelope points. That means that long (>= 16 points) + // envelopes are cut off, and envelopes have to be trimmed to 10 points, even if + // the header claims that they are longer. + Convert_RIFF_AMFF_Envelope(instheader->envflags & 0x0F, instheader->envnumpoints & 0x0F, instheader->envsustainpoints & 0x0F, instheader->envloopstarts & 0x0F, instheader->envloopends & 0x0F, instheader->volenv, &pIns->VolEnv); + Convert_RIFF_AMFF_Envelope(instheader->envflags >> 4, instheader->envnumpoints >> 4, instheader->envsustainpoints >> 4, instheader->envloopstarts >> 4, instheader->envloopends >> 4, instheader->panenv, &pIns->PanEnv); + + const size_t nTotalSmps = LittleEndianW(instheader->numsamples); + + // read sample sub-chunks - this is a rather "flat" format compared to RIFF AM and has no nested RIFF chunks. + for(size_t nSmpCnt = 0; nSmpCnt < nTotalSmps; nSmpCnt++) + { + + if(m_nSamples + 1 >= MAX_SAMPLES) + break; + + const SAMPLEINDEX nSmp = ++m_nSamples; + + MemsetZero(Samples[nSmp]); + + ASSERT_CAN_READ_CHUNK(sizeof(AMFFCHUNK_SAMPLE)); + AMFFCHUNK_SAMPLE *smpchunk = (AMFFCHUNK_SAMPLE *)(lpStream + dwMemPos); + dwMemPos += sizeof(AMFFCHUNK_SAMPLE); + + if(smpchunk->signature != AMCHUNKID_SAMP) break; // SAMP + + memcpy(m_szNames[nSmp], smpchunk->name, 28); + SpaceToNullStringFixed(m_szNames[nSmp], 28); + + Samples[nSmp].nPan = smpchunk->pan << 2; + Samples[nSmp].nVolume = smpchunk->volume << 2; + Samples[nSmp].nGlobalVol = 64; + Samples[nSmp].nLength = LittleEndian(smpchunk->length); + Samples[nSmp].nLoopStart = LittleEndian(smpchunk->loopstart); + Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend); + Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate); + + if(instheader->autovib_type < ARRAYELEMCOUNT(riffam_autovibtrans)) + Samples[nSmp].nVibType = riffam_autovibtrans[instheader->autovib_type]; + Samples[nSmp].nVibSweep = (BYTE)(LittleEndianW(instheader->autovib_sweep)); + Samples[nSmp].nVibRate = (BYTE)(LittleEndianW(instheader->autovib_rate) >> 4); + Samples[nSmp].nVibDepth = (BYTE)(LittleEndianW(instheader->autovib_depth) >> 2); + + const uint16 flags = LittleEndianW(smpchunk->flags); + if(flags & AMSMP_16BIT) + Samples[nSmp].uFlags |= CHN_16BIT; + if(flags & AMSMP_LOOP) + Samples[nSmp].uFlags |= CHN_LOOP; + if(flags & AMSMP_PINGPONG) + Samples[nSmp].uFlags |= CHN_PINGPONGLOOP; + if(flags & AMSMP_PANNING) + Samples[nSmp].uFlags |= CHN_PANNING; + + dwMemPos += ReadSample(&Samples[nSmp], (flags & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); + } } break; - case 0x46464952: // "RIFF" - Instrument (only in RIFF AM) + case AMCHUNKID_RIFF: // "RIFF" - Instrument (only in RIFF AM) if(bIsAM) { ASSERT_CAN_READ_CHUNK(4); - if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) != 0x20204941) break; // "AI " + if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) != AMCHUNKID_AI__) break; // "AI " dwMemPos += 4; ASSERT_CAN_READ_CHUNK(sizeof(AMFF_RIFFCHUNK)); - AMFF_RIFFCHUNK *instchunk = (AMFF_RIFFCHUNK *)(lpStream + dwMemPos); + const AMFF_RIFFCHUNK *instchunk = (AMFF_RIFFCHUNK *)(lpStream + dwMemPos); dwMemPos += sizeof(AMFF_RIFFCHUNK); ASSERT_CAN_READ_CHUNK(LittleEndian(instchunk->chunksize)); - if(LittleEndian(instchunk->signature) != 0x54534E49) break; // "INST" + if(LittleEndian(instchunk->signature) != AMCHUNKID_INST) break; // "INST" ASSERT_CAN_READ_CHUNK(4); - DWORD dwHeadlen = LittleEndian(*(uint32 *)(lpStream + dwMemPos)); - dwMemPos +=4 ; + const DWORD dwHeadlen = LittleEndian(*(uint32 *)(lpStream + dwMemPos)); + ASSERT(dwHeadlen == sizeof(AMCHUNK_INSTRUMENT)); + dwMemPos += 4; ASSERT_CAN_READ_CHUNK(sizeof(AMCHUNK_INSTRUMENT)); - AMCHUNK_INSTRUMENT *instheadchunk = (AMCHUNK_INSTRUMENT *)(lpStream + dwMemPos); - dwMemPos += dwHeadlen; + const AMCHUNK_INSTRUMENT *instheader = (AMCHUNK_INSTRUMENT *)(lpStream + dwMemPos); + dwMemPos += sizeof(AMCHUNK_INSTRUMENT); - SAMPLEINDEX nSmp = instheadchunk->sample + 1; - if(nSmp >= MAX_SAMPLES) + const INSTRUMENTINDEX nIns = instheader->index + 1; + if(nIns >= MAX_INSTRUMENTS) break; - m_nSamples = max(m_nSamples, nSmp); - memcpy(m_szNames[nSmp], instheadchunk->name, 32); - SpaceToNullStringFixed(m_szNames[nSmp], 31); + if(Instruments[nIns] != nullptr) + delete Instruments[nIns]; - ASSERT_CAN_READ_CHUNK(sizeof(AMFF_RIFFCHUNK)); - instchunk = (AMFF_RIFFCHUNK *)(lpStream + dwMemPos); - dwMemPos += sizeof(AMFF_RIFFCHUNK); - ASSERT_CAN_READ_CHUNK(LittleEndian(instchunk->chunksize)); - if(LittleEndian(instchunk->signature) != 0x46464952) break; // yet another "RIFF"... + MODINSTRUMENT *pIns = new MODINSTRUMENT; + if(pIns == nullptr) + break; + Instruments[nIns] = pIns; + MemsetZero(*pIns); + SetDefaultInstrumentValues(pIns); - ASSERT_CAN_READ_CHUNK(4); - if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) != 0x20205341) break; // "AS " (ain't this boring?) - dwMemPos += 4; + m_nInstruments = max(m_nInstruments, nIns); - ASSERT_CAN_READ_CHUNK(sizeof(AMCHUNK_SAMPLE)); - AMCHUNK_SAMPLE *smpchunk = (AMCHUNK_SAMPLE *)(lpStream + dwMemPos); + memcpy(pIns->name, instheader->name, 32); + SpaceToNullStringFixed(pIns->name, 31); - if(smpchunk->signature != 0x504D4153) break; // SAMP + for(BYTE i = 0; i < 128; i++) + { + pIns->NoteMap[i] = i + 1; + pIns->Keyboard[i] = instheader->samplemap[i] + m_nSamples + 1; + } - memcpy(m_szNames[nSmp], smpchunk->name, 32); - SpaceToNullStringFixed(m_szNames[nSmp], 31); + pIns->nGlobalVol = 64; + pIns->nPan = 128; + pIns->nFadeOut = LittleEndianW(instheader->volenv.fadeout) << 5; + pIns->nPPC = NOTE_MIDDLEC - 1; - if(LittleEndianW(smpchunk->pan) > 0x7FFF || LittleEndianW(smpchunk->volume) > 0x7FFF) - break; + Convert_RIFF_AM_Envelope(&instheader->volenv, &pIns->VolEnv, ENV_VOLUME); + Convert_RIFF_AM_Envelope(&instheader->pitchenv, &pIns->PitchEnv, ENV_PITCH); + Convert_RIFF_AM_Envelope(&instheader->panenv, &pIns->PanEnv, ENV_PANNING); - Samples[nSmp].nPan = LittleEndianW(smpchunk->pan) * 256 / 32767; - Samples[nSmp].nVolume = LittleEndianW(smpchunk->volume) * 256 / 32767; - Samples[nSmp].nGlobalVol = 64; - Samples[nSmp].nLength = LittleEndian(smpchunk->length); - Samples[nSmp].nLoopStart = LittleEndian(smpchunk->loopstart); - Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend); - Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate); + const size_t nTotalSmps = LittleEndianW(instheader->numsamples); - uint16 flags = LittleEndianW(smpchunk->flags); - if(flags & 0x04) - Samples[nSmp].uFlags |= CHN_16BIT; - if(flags & 0x08) - Samples[nSmp].uFlags |= CHN_LOOP; - if(flags & 0x10) - Samples[nSmp].uFlags |= CHN_PINGPONGLOOP; - if(flags & 0x20) - Samples[nSmp].uFlags |= CHN_PANNING; + DWORD dwChunkPos; - dwMemPos += LittleEndian(smpchunk->headsize) + 12; // doesn't include the 3 first DWORDs - dwMemPos += ReadSample(&Samples[nSmp], (flags & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwMemPos), dwMemLength - dwMemPos); + // read sample sub-chunks (RIFF nesting ftw) + for(size_t nSmpCnt = 0; nSmpCnt < nTotalSmps; nSmpCnt++) + { + dwChunkPos = dwMemPos; + + ASSERT_CAN_READ_CHUNK(sizeof(AMFF_RIFFCHUNK)); + instchunk = (AMFF_RIFFCHUNK *)(lpStream + dwChunkPos); + dwChunkPos += sizeof(AMFF_RIFFCHUNK); + ASSERT_CAN_READ_CHUNK(LittleEndian(instchunk->chunksize)); + if(LittleEndian(instchunk->signature) != AMCHUNKID_RIFF) break; + + ASSERT_CAN_READ_CHUNK(4); + if(LittleEndian(*(uint32 *)(lpStream + dwChunkPos)) != AMCHUNKID_AS__) break; + dwChunkPos += 4; + + 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); + SpaceToNullStringFixed(m_szNames[nSmp], 31); + + if(LittleEndianW(smpchunk->pan) > 0x7FFF || LittleEndianW(smpchunk->volume) > 0x7FFF) + break; + + Samples[nSmp].nPan = LittleEndianW(smpchunk->pan) * 256 / 32767; + Samples[nSmp].nVolume = LittleEndianW(smpchunk->volume) * 256 / 32767; + Samples[nSmp].nGlobalVol = 64; + Samples[nSmp].nLength = LittleEndian(smpchunk->length); + Samples[nSmp].nLoopStart = LittleEndian(smpchunk->loopstart); + Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend); + Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate); + + if(instheader->autovib_type < ARRAYELEMCOUNT(riffam_autovibtrans)) + Samples[nSmp].nVibType = riffam_autovibtrans[instheader->autovib_type]; + Samples[nSmp].nVibSweep = (BYTE)(LittleEndianW(instheader->autovib_sweep)); + Samples[nSmp].nVibRate = (BYTE)(LittleEndianW(instheader->autovib_rate) >> 4); + Samples[nSmp].nVibDepth = (BYTE)(LittleEndianW(instheader->autovib_depth) >> 2); + + const uint16 flags = LittleEndianW(smpchunk->flags); + if(flags & AMSMP_16BIT) + Samples[nSmp].uFlags |= CHN_16BIT; + if(flags & AMSMP_LOOP) + Samples[nSmp].uFlags |= CHN_LOOP; + if(flags & AMSMP_PINGPONG) + Samples[nSmp].uFlags |= CHN_PINGPONGLOOP; + if(flags & AMSMP_PANNING) + Samples[nSmp].uFlags |= CHN_PANNING; + + dwChunkPos += LittleEndian(smpchunk->headsize) + 12; // doesn't include the 3 first DWORDs + dwChunkPos += ReadSample(&Samples[nSmp], (flags & 0x04) ? RS_PCM16S : RS_PCM8S, (LPCSTR)(lpStream + dwChunkPos), dwMemLength - dwChunkPos); + + dwMemPos += LittleEndian(instchunk->chunksize) + sizeof(AMFF_RIFFCHUNK); + // RIFF AM has a padding byte so that all chunks have an even size. + if(LittleEndian(instchunk->chunksize) & 1) + dwMemPos++; + + } } break; @@ -483,9 +786,9 @@ ASSERT_CAN_READ(sizeof(J2BHEADER)); J2BHEADER *header = (J2BHEADER *)lpStream; - if(LittleEndian(header->signature) != 0x4553554D // "MUSE" - || (LittleEndian(header->deadbeaf) != 0xAFBEADDE // 0xDEADBEAF (RIFF AM) - && LittleEndian(header->deadbeaf) != 0xBEBAADDE) // 0xDEADBABE (RIFF AMFF) + if(LittleEndian(header->signature) != J2BHEAD_MUSE // "MUSE" + || (LittleEndian(header->deadbeaf) != J2BHEAD_DEADBEAF // 0xDEADBEAF (RIFF AM) + && LittleEndian(header->deadbeaf) != J2BHEAD_DEADBABE) // 0xDEADBABE (RIFF AMFF) || LittleEndian(header->j2blength) != dwMemLength || LittleEndian(header->packed_length) != dwMemLength - sizeof(J2BHEADER) || LittleEndian(header->packed_length) == 0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-01 21:47:40
|
Revision: 634 http://modplug.svn.sourceforge.net/modplug/?rev=634&view=rev Author: saga-games Date: 2010-07-01 21:47:33 +0000 (Thu, 01 Jul 2010) Log Message: ----------- [Fix] S3M Compatibility: SD0 was not ignored properly when there was a row delay effect on the same row. Now it should be ignored in any case. [Imp] Treeview: Don't ask for deleting for order items, as it was a bit annoying restoring them isn't a difficult task anyway. [Imp] Sample Editor: When using the spin buttons for finetune, the finetune value is always in/decreased by 16 in MOD format. Not perfect yet, but at least better than before. [Mod] Changes some keyboard manager shortcut names [Mod] OpenMPT: Version is now 1.18.02.02 [Ref] Some minor code changes Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/mptrack/Ctrl_smp.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Load_gdm.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/load_j2b.cpp Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -1822,7 +1822,7 @@ commands[kcFileSaveAsMP3].isDummy = false; commands[kcFileSaveMidi].UID = 1353; - commands[kcFileSaveMidi].Message = "File/Export to Midi"; + commands[kcFileSaveMidi].Message = "File/Export as MIDI"; commands[kcFileSaveMidi].isHidden = false; commands[kcFileSaveMidi].isDummy = false; @@ -2266,7 +2266,7 @@ commands[kcChangeLoopStatus].Message = "Toggle loop pattern"; commands[kcFileExportCompat].UID = 1777; - commands[kcFileExportCompat].Message = "File/Export to standard IT/XM"; + commands[kcFileExportCompat].Message = "File/Export to standard IT/XM/S3M"; commands[kcFileExportCompat].isHidden = false; commands[kcFileExportCompat].isDummy = false; Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -316,7 +316,7 @@ pSndFile->m_nCurrentPattern = m_nScrollPos; pSndFile->SetCurrentOrder(m_nScrollPos); pSndFile->m_dwSongFlags |= dwPaused; - if (!(dwPaused & SONG_PATTERNLOOP)) pSndFile->GetLength(TRUE); + if (!(dwPaused & SONG_PATTERNLOOP)) pSndFile->GetLength(TRUE); // update channel parameters if (bIsPlaying) pMainFrm->ResetNotificationBuffer(); END_CRITICAL(); } Modified: trunk/OpenMPT/mptrack/Ctrl_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/mptrack/Ctrl_smp.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -2956,7 +2956,7 @@ m_EditFineTune.SetWindowText(s); } else { - LONG d = CLAMP(pSmp->nFineTune + pos, -128, 127); + LONG d = CLAMP(pSmp->nFineTune + pos * ((m_pSndFile->GetType() & MOD_TYPE_MOD) ? 16 : 1), -128, 127); pSmp->nFineTune = (signed char)d; wsprintf(s, "%d", d); m_EditFineTune.SetWindowText(s); Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -1411,8 +1411,6 @@ break; case MODITEM_ORDER: - wsprintf(s, _T("Delete order %d?"), modItemID & 0xFFFF); - if(MessageBox(s, _T("Confirmation"), MB_YESNO | MB_DEFBUTTON2) == IDNO) break; if ((pModDoc) && (pModDoc->RemoveOrder((SEQUENCEINDEX)(modItemID >> 16), (ORDERINDEX)(modItemID & 0xFFFF)))) { pModDoc->UpdateAllViews(NULL, HINT_MODSEQUENCE, NULL); Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/mptrack/version.h 2010-07-01 21:47:33 UTC (rev 634) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 #define VER_MINOR 02 -#define VER_MINORMINOR 01 +#define VER_MINORMINOR 02 //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_gdm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -71,8 +71,7 @@ #pragma pack() -#define GDMHeader_Origin_Count 9 -static MODTYPE GDMHeader_Origin[GDMHeader_Origin_Count] = +static MODTYPE GDMHeader_Origin[] = { MOD_TYPE_NONE, MOD_TYPE_MOD, MOD_TYPE_MTM, MOD_TYPE_S3M, MOD_TYPE_669, MOD_TYPE_FAR, MOD_TYPE_ULT, MOD_TYPE_STM, MOD_TYPE_MED }; @@ -94,7 +93,7 @@ return false; // 1-MOD, 2-MTM, 3-S3M, 4-669, 5-FAR, 6-ULT, 7-STM, 8-MED - m_nType = GDMHeader_Origin[pHeader->FormOrigin % GDMHeader_Origin_Count]; + m_nType = GDMHeader_Origin[pHeader->FormOrigin % ARRAYELEMCOUNT(GDMHeader_Origin)]; if(m_nType == MOD_TYPE_NONE) return false; @@ -175,7 +174,7 @@ Samples[iSmp].nLoopEnd = min(LittleEndian(pSample->LoopEnd) - 1, Samples[iSmp].nLength); // dito FrequencyToTranspose(&Samples[iSmp]); // set transpose + finetune for mod files - // fix transpose + finetune for some rare cases where transpose is not C-5 (e.g. sample 4 in wander2.mod) + // fix transpose + finetune for some rare cases where transpose is not C-5 (e.g. sample 4 in wander2.gdm) if(m_nType == MOD_TYPE_MOD) { while(Samples[iSmp].RelativeTone != 0) Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -1293,7 +1293,7 @@ nStartTick = 1; //ST3 ignores notes with SD0 completely else if(GetType() == MOD_TYPE_S3M) - nStartTick = m_nMusicSpeed; + nStartTick = UINT_MAX; } //IT compatibility 08. Handling of out-of-range delay command. Modified: trunk/OpenMPT/soundlib/load_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-06-26 14:04:46 UTC (rev 633) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-07-01 21:47:33 UTC (rev 634) @@ -467,6 +467,8 @@ else return false; dwMemPos += 4; m_nChannels = 0; + m_nSamples = 0; + m_nInstruments = 0; // go through all chunks now while(dwMemPos < dwMemLength) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-04 14:41:45
|
Revision: 635 http://modplug.svn.sourceforge.net/modplug/?rev=635&view=rev Author: saga-games Date: 2010-07-04 14:41:38 +0000 (Sun, 04 Jul 2010) Log Message: ----------- [Imp] Instrument Editor / XM Saver: For XM, allow fadeout values up to 32767 again, as FT2 can actually handle them (and other apps like Milky support them as well) [New] Sample Editor: It's not also possible to create sample selections using shift+click. [Ref] A bit of refactoring Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-01 21:47:33 UTC (rev 634) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-04 14:41:38 UTC (rev 635) @@ -183,13 +183,14 @@ if ((pIns) && (nPos >= 0) && (nPos < NOTE_MAX) && (pIns->NoteMap[nPos])) { UINT n = pIns->NoteMap[nPos]; - if (n == NOTE_KEYOFF) strcpy(s, "==="); else - if (n == NOTE_NOTECUT) strcpy(s, "^^^"); else - if (n <= NOTE_MAX) + if(n < NOTE_MIN_SPECIAL) { string temp = pSndFile->GetNoteName(n, m_nInstrument); temp.resize(4); wsprintf(s, "%s", temp.c_str()); + } else + { + strcpy(s, szSpecialNoteNames[pIns->NoteMap[n] - NOTE_MIN_SPECIAL]); } } FillRect(hdc, &rect, (bHighLight) ? CMainFrame::brushHighLight : CMainFrame::brushWindow); @@ -658,7 +659,7 @@ case VK_TAB: return true; case VK_RETURN: - if (m_pModDoc) + if (m_pModDoc && m_pModDoc->GetSoundFile()) { MODINSTRUMENT *pIns = m_pModDoc->GetSoundFile()->Instruments[m_nInstrument]; if(pIns) @@ -680,20 +681,24 @@ return false; } + void CNoteMapWnd::PlayNote(int note) +//---------------------------------- { - if (m_nPlayingNote >=0) return; //no polyphony in notemap window + if(m_nPlayingNote >= 0) return; //no polyphony in notemap window m_pModDoc->PlayNote(note, m_nInstrument, 0, FALSE); - m_nPlayingNote=note; + m_nPlayingNote = note; } + void CNoteMapWnd::StopNote(int note = -1) +//---------------------------------- { - if (note<0) note = m_nPlayingNote; - if (note<0) return; + if(note < 0) note = m_nPlayingNote; + if(note < 0) return; m_pModDoc->NoteOff(note, TRUE, m_nInstrument); - m_nPlayingNote=-1; + m_nPlayingNote = -1; } //end rewbs.customKeys @@ -872,7 +877,8 @@ m_SpinMidiBK.SetRange(0, 128); // Midi Channel //rewbs.instroVSTi: we no longer combine midi chan and FX in same cbbox - for (UINT ich=0; ich<17; ich++) { + for (UINT ich=0; ich<17; ich++) + { UINT n = 0; s[0] = 0; if (!ich) { strcpy(s, "None"); n=0; } @@ -1115,7 +1121,7 @@ m_SpinFadeOut.EnableWindow(bITandXM); if(m_pSndFile->m_nType & MOD_TYPE_XM) - m_SpinFadeOut.SetRange(0, 4095); + m_SpinFadeOut.SetRange(0, 32767); else m_SpinFadeOut.SetRange(0, 8192); @@ -1768,9 +1774,9 @@ if ((!IsLocked()) && (pIns)) { int nVol = GetDlgItemInt(IDC_EDIT7); - if (nVol < 0) nVol = 0; - if (nVol > 16384) nVol = 16384; - if (nVol != (int)pIns->nFadeOut) + nVol = CLAMP(nVol, 0, 32767); + + if(nVol != (int)pIns->nFadeOut) { pIns->nFadeOut = nVol; m_pModDoc->SetModified(); Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2010-07-01 21:47:33 UTC (rev 634) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2010-07-04 14:41:38 UTC (rev 635) @@ -1340,35 +1340,45 @@ if ((m_dwStatus & SMPSTATUS_MOUSEDRAG) || (!pModDoc)) return; pSndFile = pModDoc->GetSoundFile(); len = pSndFile->Samples[m_nSample].nLength; - if (len) + if (!len) + return; + + m_dwStatus |= SMPSTATUS_MOUSEDRAG; + SetFocus(); + SetCapture(); + bool oldsel = (m_dwBeginSel != m_dwEndSel) ? true : false; + + // shift + click = update selection + if(CMainFrame::GetInputHandler()->ShiftPressed()) { - m_dwStatus |= SMPSTATUS_MOUSEDRAG; - SetFocus(); - SetCapture(); - BOOL oldsel = (m_dwBeginSel != m_dwEndSel) ? TRUE : FALSE; + oldsel = true; + m_dwEndDrag = ScreenToSample(point.x); + SetCurSel(m_dwBeginDrag, m_dwEndDrag); + } else + { m_dwBeginDrag = ScreenToSample(point.x); if (m_dwBeginDrag >= len) m_dwBeginDrag = len-1; m_dwEndDrag = m_dwBeginDrag; - if (oldsel) SetCurSel(m_dwBeginDrag, m_dwEndDrag); - // set initial point for sample drawing - if (m_bDrawingEnabled) - { - pModDoc->GetSampleUndo()->PrepareUndo(m_nSample, sundo_replace); - if(pSndFile->Samples[m_nSample].GetElementarySampleSize() == 2) - SetInitialDrawPoint<int16, uint16>(pSndFile->Samples[m_nSample].pSample, point); - else if(pSndFile->Samples[m_nSample].GetElementarySampleSize() == 1) - SetInitialDrawPoint<int8, uint8>(pSndFile->Samples[m_nSample].pSample, point); + } + if (oldsel) SetCurSel(m_dwBeginDrag, m_dwEndDrag); + // set initial point for sample drawing + if (m_bDrawingEnabled) + { + pModDoc->GetSampleUndo()->PrepareUndo(m_nSample, sundo_replace); + if(pSndFile->Samples[m_nSample].GetElementarySampleSize() == 2) + SetInitialDrawPoint<int16, uint16>(pSndFile->Samples[m_nSample].pSample, point); + else if(pSndFile->Samples[m_nSample].GetElementarySampleSize() == 1) + SetInitialDrawPoint<int8, uint8>(pSndFile->Samples[m_nSample].pSample, point); - InvalidateSample(); - pModDoc->SetModified(); - } - else - { - // ctrl + click = play from cursor pos - if(CMainFrame::GetInputHandler()->CtrlPressed()) - PlayNote(NOTE_MIDDLEC, ScreenToSample(point.x)); - } + InvalidateSample(); + pModDoc->SetModified(); } + else + { + // ctrl + click = play from cursor pos + if(CMainFrame::GetInputHandler()->CtrlPressed()) + PlayNote(NOTE_MIDDLEC, ScreenToSample(point.x)); + } } @@ -1822,6 +1832,7 @@ if (pSmp->uFlags & (CHN_LOOP|CHN_SUSTAINLOOP)) { WAVESAMPLERINFO *psmpl = (WAVESAMPLERINFO *)psh; + MemsetZero(psmpl->wsiLoops); if (pSmp->uFlags & CHN_SUSTAINLOOP) { psmpl->wsiHdr.dwSampleLoops = 2; Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-01 21:47:33 UTC (rev 634) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-04 14:41:38 UTC (rev 635) @@ -956,7 +956,7 @@ { memcpy(xmih.name, pIns->name, 22); xmih.type = pIns->nMidiProgram; - xmsh.volfade = LittleEndianW(min(pIns->nFadeOut, 0xFFF)); // FFF is maximum in FT2 + xmsh.volfade = LittleEndianW(min(pIns->nFadeOut, 0x7FFF)); // FFF is maximum in the FT2 GUI, but it can also accept other values. MilkyTracker just allows 0...4095 and 32767 ("cut") xmsh.vnum = (BYTE)pIns->VolEnv.nNodes; xmsh.pnum = (BYTE)pIns->PanEnv.nNodes; if (xmsh.vnum > 12) xmsh.vnum = 12; Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-01 21:47:33 UTC (rev 634) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-04 14:41:38 UTC (rev 635) @@ -3038,17 +3038,16 @@ return 0; } -string CSoundFile::GetNoteName(const CTuning::NOTEINDEXTYPE& note, const int inst) const +string CSoundFile::GetNoteName(const CTuning::NOTEINDEXTYPE& note, const INSTRUMENTINDEX inst) const //---------------------------------------------------------------------------------- { - if(inst >= MAX_INSTRUMENTS || inst < -1 || note < 1 || note > NOTE_MAX) return "BUG"; - if(inst == -1) - return szDefaultNoteNames[note-1]; - - if(m_nType == MOD_TYPE_MPT && Instruments[inst] && Instruments[inst]->pTuning) - return Instruments[inst]->pTuning->GetNoteName(note-NOTE_MIDDLEC); + if((inst >= MAX_INSTRUMENTS && inst != INSTRUMENTINDEX_INVALID) || note < 1 || note > NOTE_MAX) return "BUG"; + + // For MPTM instruments with custom tuning, find the appropriate note name. Else, use default note names. + if(inst != INSTRUMENTINDEX_INVALID && m_nType == MOD_TYPE_MPT && Instruments[inst] && Instruments[inst]->pTuning) + return Instruments[inst]->pTuning->GetNoteName(note - NOTE_MIDDLEC); else - return szDefaultNoteNames[note-1]; + return szDefaultNoteNames[note - 1]; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-01 21:47:33 UTC (rev 634) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-04 14:41:38 UTC (rev 635) @@ -99,8 +99,8 @@ INSTRUMENTENVELOPE PanEnv; INSTRUMENTENVELOPE PitchEnv; - BYTE NoteMap[128]; - WORD Keyboard[128]; + BYTE NoteMap[128]; // Note mapping, f.e. C-5 => D-5 + WORD Keyboard[128]; // Sample mapping, f.e. C-5 => Sample 1 BYTE nNNA; BYTE nDCT; @@ -495,7 +495,7 @@ static CTuningCollection& GetLocalTunings() {return *s_pTuningsSharedLocal;} CTuningCollection& GetTuneSpecificTunings() {return *m_pTuningsTuneSpecific;} - std::string GetNoteName(const int16&, const int inst = -1) const; + std::string GetNoteName(const int16&, const INSTRUMENTINDEX inst = INSTRUMENTINDEX_INVALID) const; private: CTuningCollection* m_pTuningsTuneSpecific; static CTuningCollection* s_pTuningsSharedBuiltIn; @@ -724,13 +724,13 @@ 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 = nullptr); +#endif // MODPLUG_NO_FILESAVE // 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 = nullptr); -#endif // MODPLUG_NO_FILESAVE // MOD Convert function MODTYPE GetBestSaveFormat() const; MODTYPE GetSaveFormats() const; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-10 12:04:00
|
Revision: 636 http://modplug.svn.sourceforge.net/modplug/?rev=636&view=rev Author: saga-games Date: 2010-07-10 12:03:54 +0000 (Sat, 10 Jul 2010) Log Message: ----------- [Fix] IT Saver: Instrument panning was not converted properly. [Imp] Instrument editor: Panning ranges from 0 to 256 again for MPTM, and from 0 to 64 for IT files. [Imp] J2B Loader: Added some security checks for sample and pattern length [Mod] Sample Generator (still unused): Using the fmod command for module operations. [Ref] Some refactoring, especially regarding the "instrumentModified" array. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/SampleGenerator.h trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mod.cpp trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/load_j2b.cpp trunk/OpenMPT/soundlib/patternContainer.h Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -870,7 +870,7 @@ // Global Volume m_SpinGlobalVol.SetRange(0, 64); // Panning - m_SpinPanning.SetRange(0, 255); + m_SpinPanning.SetRange(0, (m_pModDoc->GetModType() & MOD_TYPE_IT) ? 64 : 256); // Midi Program m_SpinMidiPR.SetRange(0, 128); // rewbs.MidiBank @@ -1172,7 +1172,7 @@ // Global Volume SetDlgItemInt(IDC_EDIT8, pIns->nGlobalVol); // Panning - SetDlgItemInt(IDC_EDIT9, pIns->nPan); + SetDlgItemInt(IDC_EDIT9, (m_pModDoc->GetModType() & MOD_TYPE_IT) ? (pIns->nPan / 4) : pIns->nPan); m_CheckPanning.SetCheck((pIns->dwFlags & INS_SETPANNING) ? TRUE : FALSE); // Midi if (pIns->nMidiProgram>0 && pIns->nMidiProgram<=128) @@ -1838,14 +1838,14 @@ } if(smpPanningInUse) { - if(MessageBox("Some of the samples used in the instrument have \"Set Pan\" enabled. " + if(MessageBox(_T("Some of the samples used in the instrument have \"Set Pan\" enabled. " "When instrument is played with such sample, sample pan setting overrides instrument pan. " "Do you wish to disable panning from those samples so that instrument pan setting is effective " - "for the whole instrument?", - "", + "for the whole instrument?"), + _T(""), MB_YESNO) == IDYES) { - for(BYTE i = 0; i<ARRAYELEMCOUNT(pIns->Keyboard); i++) + for(BYTE i = 0; i < ARRAYELEMCOUNT(pIns->Keyboard); i++) { const SAMPLEINDEX smp = pIns->Keyboard[i]; if(smp <= m_pSndFile->GetNumSamples()) @@ -1874,6 +1874,8 @@ if ((!IsLocked()) && (pIns)) { int nPan = GetDlgItemInt(IDC_EDIT9); + if(m_pModDoc->GetModType() & MOD_TYPE_IT) // IT panning ranges from 0 to 64 + nPan *= 4; if (nPan < 0) nPan = 0; if (nPan > 256) nPan = 256; if (nPan != (int)pIns->nPan) @@ -1882,7 +1884,7 @@ if (m_pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT)) m_pModDoc->SetModified(); // -> CODE#0023 // -> DESC="IT project files (.itp)" - m_pSndFile->instrumentModified[m_nInstrument-1] = TRUE; + m_pSndFile->instrumentModified[m_nInstrument - 1] = true; m_pModDoc->UpdateAllViews(NULL, HINT_INSNAMES, this); // -! NEW_FEATURE#0023 } @@ -1903,7 +1905,7 @@ // -> CODE#0023 // -> DESC="IT project files (.itp)" - m_pSndFile->instrumentModified[m_nInstrument-1] = TRUE; + m_pSndFile->instrumentModified[m_nInstrument - 1] = true; m_pModDoc->UpdateAllViews(NULL, HINT_INSNAMES, this); // -! NEW_FEATURE#0023 Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -452,10 +452,10 @@ { if((m_SndFile.m_nType & MOD_TYPE_IT) && m_SndFile.m_dwSongFlags & SONG_ITPROJECT && !(m_SndFile.m_dwSongFlags & SONG_ITPEMBEDIH)){ - BOOL unsavedInstrument = FALSE; + bool unsavedInstrument = false; for(UINT i = 0 ; i < m_SndFile.m_nInstruments ; i++){ - if(m_SndFile.instrumentModified[i]) { unsavedInstrument = TRUE; break; } + if(m_SndFile.instrumentModified[i]) { unsavedInstrument = true; break; } } if(unsavedInstrument && ::MessageBox(NULL,"Do you want to save modified instruments ?",NULL,MB_ICONQUESTION | MB_YESNO | MB_APPLMODAL) == IDYES){ @@ -463,8 +463,8 @@ for(INSTRUMENTINDEX i = 0 ; i < m_SndFile.m_nInstruments ; i++){ if(m_SndFile.m_szInstrumentPath[i][0] != '\0'){ int size = strlen(m_SndFile.m_szInstrumentPath[i]); - BOOL iti = _stricmp(&m_SndFile.m_szInstrumentPath[i][size-3],"iti") == 0; - BOOL xi = _stricmp(&m_SndFile.m_szInstrumentPath[i][size-2],"xi") == 0; + bool iti = _stricmp(&m_SndFile.m_szInstrumentPath[i][size-3],"iti") == 0; + bool xi = _stricmp(&m_SndFile.m_szInstrumentPath[i][size-2],"xi") == 0; if(iti || (!iti && !xi && m_SndFile.m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT))) m_SndFile.SaveITIInstrument(i+1, m_SndFile.m_szInstrumentPath[i]); Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -822,7 +822,7 @@ // -> CODE#0023 // -> DESC="IT project files (.itp)" strcpy(m_SndFile.m_szInstrumentPath[newins - 1], m_SndFile.m_szInstrumentPath[nDuplicate - 1]); - m_SndFile.instrumentModified[newins-1] = FALSE; + m_SndFile.instrumentModified[newins - 1] = false; // -! NEW_FEATURE#0023 } else { Modified: trunk/OpenMPT/mptrack/SampleGenerator.h =================================================================== --- trunk/OpenMPT/mptrack/SampleGenerator.h 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/mptrack/SampleGenerator.h 2010-07-10 12:03:54 UTC (rev 636) @@ -17,7 +17,7 @@ #define SMPGEN_MAXLENGTH MAX_SAMPLE_LENGTH // sample frequency #define SMPGEN_MINFREQ 1 -#define SMPGEN_MAXFREQ 96000 +#define SMPGEN_MAXFREQ 96000 // MAX_SAMPLE_RATE // 16-bit sample quality - when changing this, also change CSampleGenerator::sampling_type and 16-bit flags in SampleGenerator.cpp! #define SMPGEN_MIXBYTES 2 @@ -53,13 +53,13 @@ // Rendering callback functions // functions static mu::value_type ClipCallback(mu::value_type val, mu::value_type min, mu::value_type max) { return CLAMP(val, min, max); }; - static mu::value_type PWMCallback(mu::value_type pos, mu::value_type duty, mu::value_type width) { if((int)width == 0) return 0; else return (((int)pos % (int)width) < ((duty / 100) * width)) ? 1 : -1; }; - static mu::value_type RndCallback(mu::value_type v) { return v*std::rand()/(mu::value_type)(RAND_MAX+1.0); } + static mu::value_type PWMCallback(mu::value_type pos, mu::value_type duty, mu::value_type width) { if(width == 0) return 0; else return (fmod(pos, width) < ((duty / 100) * width)) ? 1 : -1; }; + static mu::value_type RndCallback(mu::value_type v) { return v*std::rand()/(mu::value_type)(RAND_MAX+1.0); }; static mu::value_type SampleDataCallback(mu::value_type v); static mu::value_type TriangleCallback(mu::value_type pos, mu::value_type width) { if((int)width == 0) return 0; else return abs(((int)pos % (int)(width)) - width / 2) / (width / 4) - 1; }; // binary operators - static mu::value_type ModuloCallback(mu::value_type x, mu::value_type y) { if((int)y == 0) return 0; else return ((int)x) % ((int)y); }; + static mu::value_type ModuloCallback(mu::value_type x, mu::value_type y) { if(y == 0) return 0; else return fmod(x , y); }; void ShowError(mu::Parser::exception_type *e); @@ -136,10 +136,10 @@ public: - int GetFrequency() { return sample_frequency; }; - int GetLength() { return sample_length; }; - smpgen_clip_methods GetClipping() { return sample_clipping; } - mu::string_type GetExpression() { return expression; }; + const int GetFrequency() { return sample_frequency; }; + const int GetLength() { return sample_length; }; + const smpgen_clip_methods GetClipping() { return sample_clipping; } + const mu::string_type GetExpression() { return expression; }; bool CanApply() { return apply; }; CSmpGenDialog(int freq, int len, smpgen_clip_methods clipping, mu::string_type expr):CDialog(IDD_SAMPLE_GENERATOR, CMainFrame::GetMainFrame()) Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -968,8 +968,8 @@ if((pSndFile->m_dwSongFlags & SONG_ITPROJECT) != 0) { // path info for ITP instruments - BOOL pathOk = pSndFile->m_szInstrumentPath[nIns-1][0] != '\0'; - BOOL instOk = pSndFile->instrumentModified[nIns-1] == FALSE; + bool pathOk = pSndFile->m_szInstrumentPath[nIns-1][0] != '\0'; + bool instOk = pSndFile->instrumentModified[nIns-1] == false; wsprintf(s, pathOk ? (instOk ? "%3d: %s" : "%3d: * %s") : "%3d: ? %s", nIns, (LPCTSTR)pSndFile->GetInstrumentName(nIns)); } else { @@ -3058,7 +3058,7 @@ if(xi || (!xi && !iti && pSndFile->m_nType == MOD_TYPE_XM)) pSndFile->SaveXIInstrument((INSTRUMENTINDEX)modItemID, pSndFile->m_szInstrumentPath[modItemID - 1]); - pSndFile->instrumentModified[modItemID - 1] = FALSE; + pSndFile->instrumentModified[modItemID - 1] = false; } if(pModDoc) pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -2065,7 +2065,7 @@ iti.pps = pIns->nPPS; iti.ppc = pIns->nPPC; iti.gbv = (BYTE)(pIns->nGlobalVol << 1); - iti.dfp = (BYTE)pIns->nPan >> 2; + iti.dfp = (BYTE)(pIns->nPan >> 2); if (!(pIns->dwFlags & INS_SETPANNING)) iti.dfp |= 0x80; iti.rv = pIns->nVolSwing; iti.rp = pIns->nPanSwing; @@ -2664,7 +2664,7 @@ iti.pps = pIns->nPPS; iti.ppc = pIns->nPPC; iti.gbv = (BYTE)(pIns->nGlobalVol << 1); - iti.dfp = (BYTE)pIns->nPan >> 2; + iti.dfp = (BYTE)(pIns->nPan >> 2); if (!(pIns->dwFlags & INS_SETPANNING)) iti.dfp |= 0x80; iti.rv = pIns->nVolSwing; iti.rp = pIns->nPanSwing; Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -428,7 +428,7 @@ } // Reading samples - DWORD dwErrCheck = 0; + bool bSamplesPresent = false; for (UINT ismp = 1; ismp <= m_nSamples; ismp++) if (Samples[ismp].nLength) { LPSTR p = (LPSTR)(lpStream + dwMemPos); @@ -446,13 +446,13 @@ if (dwSize) { dwMemPos += dwSize; - dwErrCheck++; + bSamplesPresent = true; } } #ifdef MODPLUG_TRACKER return true; #else - return (dwErrCheck) ? true : false; + return bSamplesPresent; #endif } Modified: trunk/OpenMPT/soundlib/Snd_defs.h =================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/Snd_defs.h 2010-07-10 12:03:54 UTC (rev 636) @@ -16,6 +16,7 @@ typedef uint32 ROWINDEX; const ROWINDEX ROWINDEX_MAX = uint32_max; + const ROWINDEX ROWINDEX_INVALID = ROWINDEX_MAX; typedef uint16 CHANNELINDEX; const CHANNELINDEX CHANNELINDEX_MAX = uint16_max; const CHANNELINDEX CHANNELINDEX_INVALID = CHANNELINDEX_MAX; @@ -358,15 +359,19 @@ NUM_SRC_MODES }; -enum { +// Envelope reset choices +enum enmResetEnv +{ ENV_RESET_ALL, ENV_RESET_VOL, ENV_RESET_PAN, ENV_RESET_PITCH, - ENV_RELEASE_NODE_UNSET=0xFF, - NOT_YET_RELEASED=-1 }; +// Release node defines +#define ENV_RELEASE_NODE_UNSET 0xFF +#define NOT_YET_RELEASED (-1) + enum { CHANNEL_ONLY = 0, INSTRUMENT_ONLY = 1, Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -2057,8 +2057,8 @@ return TRUE; } -void CSoundFile::resetEnvelopes(MODCHANNEL* pChn, int envToReset) -//--------------------------------------------------------------- +void CSoundFile::resetEnvelopes(MODCHANNEL* pChn, enmResetEnv envToReset) +//----------------------------------------------------------------------- { switch (envToReset) { @@ -4153,8 +4153,7 @@ { if(bAutoSet) SetRowVisited(nOrd, nRow, true); - else - return false; + return false; } if(m_bVisitedRows[nOrd][nRow]) Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -481,9 +481,10 @@ // -> CODE#0023 // -> DESC="IT project files (.itp)" - for(UINT i = 0 ; i < MAX_INSTRUMENTS ; i++){ + for(UINT i = 0; i < MAX_INSTRUMENTS; i++) + { m_szInstrumentPath[i][0] = '\0'; - instrumentModified[i] = FALSE; + instrumentModified[i] = false; } // -! NEW_FEATURE#0023 @@ -3137,7 +3138,7 @@ const CModSpecifications& CSoundFile::GetModSpecifications(const MODTYPE type) //---------------------------------------------------------------------------- { - const CModSpecifications* p = 0; + const CModSpecifications* p = nullptr; SetModSpecsPointer(p, type); return *p; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-10 12:03:54 UTC (rev 636) @@ -949,7 +949,7 @@ public: int getVolEnvValueFromPosition(int position, MODINSTRUMENT* pIns); - void resetEnvelopes(MODCHANNEL* pChn, int envToReset = ENV_RESET_ALL); + void resetEnvelopes(MODCHANNEL* pChn, enmResetEnv envToReset = ENV_RESET_ALL); void SetDefaultInstrumentValues(MODINSTRUMENT *pIns); private: UINT __cdecl GetChannelPlugin(UINT nChan, bool respectMutes); Modified: trunk/OpenMPT/soundlib/load_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-07-10 12:03:54 UTC (rev 636) @@ -217,7 +217,7 @@ ASSERT_CAN_READ(1); - ROWINDEX nRows = lpStream[0] + 1; + ROWINDEX nRows = CLAMP(lpStream[0] + 1, 1, MAX_PATTERN_ROWS); if(pSndFile == nullptr || pSndFile->Patterns.Insert(nPat, nRows)) return false; @@ -610,7 +610,7 @@ Samples[nSmp].nPan = smpchunk->pan << 2; Samples[nSmp].nVolume = smpchunk->volume << 2; Samples[nSmp].nGlobalVol = 64; - Samples[nSmp].nLength = LittleEndian(smpchunk->length); + Samples[nSmp].nLength = min(LittleEndian(smpchunk->length), MAX_SAMPLE_LENGTH); Samples[nSmp].nLoopStart = LittleEndian(smpchunk->loopstart); Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend); Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate); @@ -731,7 +731,7 @@ Samples[nSmp].nPan = LittleEndianW(smpchunk->pan) * 256 / 32767; Samples[nSmp].nVolume = LittleEndianW(smpchunk->volume) * 256 / 32767; Samples[nSmp].nGlobalVol = 64; - Samples[nSmp].nLength = LittleEndian(smpchunk->length); + Samples[nSmp].nLength = min(LittleEndian(smpchunk->length), MAX_SAMPLE_LENGTH); Samples[nSmp].nLoopStart = LittleEndian(smpchunk->loopstart); Samples[nSmp].nLoopEnd = LittleEndian(smpchunk->loopend); Samples[nSmp].nC5Speed = LittleEndian(smpchunk->samplerate); Modified: trunk/OpenMPT/soundlib/patternContainer.h =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.h 2010-07-04 14:41:38 UTC (rev 635) +++ trunk/OpenMPT/soundlib/patternContainer.h 2010-07-10 12:03:54 UTC (rev 636) @@ -35,7 +35,7 @@ void ClearPatterns() {m_Patterns.assign(m_Patterns.size(), MODPATTERN(*this));} //Insert (default)pattern to given position. If pattern already exists at that position, - //ignoring request. + //ignoring request. Returns true on failure, false otherwise. bool Insert(const PATTERNINDEX index, const ROWINDEX rows); //Insert pattern to position with the lowest index, and return that index, PATTERNINDEX_INVALID This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-10 13:37:51
|
Revision: 638 http://modplug.svn.sourceforge.net/modplug/?rev=638&view=rev Author: saga-games Date: 2010-07-10 13:37:44 +0000 (Sat, 10 Jul 2010) Log Message: ----------- [Imp] OKT Loader: Compltely new IFF-based loader, translated from SchismTracker code with permission from Storlek. This loader is a *lot* more accurate, but still misses a few pattern effects. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/soundlib/Load_okt.cpp Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2010-07-10 12:09:43 UTC (rev 637) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2010-07-10 13:37:44 UTC (rev 638) @@ -1857,7 +1857,7 @@ "coda for sample drawing code|" "http://coda.s3m.us/|" "Storlek for all the IT compatibility hints and testcases|" - "as well as the IMF and ULT loaders|" + "as well as the IMF, OKT and ULT loaders|" "http://schismtracker.org/|" "kode54 for the PSM and J2B loaders|" "http://kode54.foobar2000.org/|" Modified: trunk/OpenMPT/soundlib/Load_okt.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_okt.cpp 2010-07-10 12:09:43 UTC (rev 637) +++ trunk/OpenMPT/soundlib/Load_okt.cpp 2010-07-10 13:37:44 UTC (rev 638) @@ -1,12 +1,10 @@ /* - * This source code is public domain. + * Purpose: Load OKT (Oktalyzer) modules + * Authors: Storlek (Original author - http://schismtracker.org/) + * Johannes Schultz (OpenMPT Port, tweaks) * - * Copied to OpenMPT from libmodplug. - * - * Authors: Olivier Lapicque <oli...@jp...>, - * Adam Goode <ad...@ev...> (endian and char fixes for PPC) - * -*/ + * Thanks to Storlek for allowing me to use this code! + */ ////////////////////////////////////////////// // Oktalyzer (OKT) module loader // @@ -14,189 +12,432 @@ #include "stdafx.h" #include "sndfile.h" -#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" +// IFF chunk names +#define OKTCHUNKID_CMOD 0x434D4F44 +#define OKTCHUNKID_SAMP 0x53414D50 +#define OKTCHUNKID_SPEE 0x53504545 +#define OKTCHUNKID_SLEN 0x534C454E +#define OKTCHUNKID_PLEN 0x504C454E +#define OKTCHUNKID_PATT 0x50415454 +#define OKTCHUNKID_PBOD 0x50424F44 +#define OKTCHUNKID_SBOD 0x53424F44 -typedef struct OKTFILEHEADER +#pragma pack(1) + +struct OKT_IFFCHUNK { - DWORD okta; // "OKTA" - DWORD song; // "SONG" - DWORD cmod; // "CMOD" - DWORD fixed8; - BYTE chnsetup[8]; - DWORD samp; // "SAMP" - DWORD samplen; -} OKTFILEHEADER; + uint32 signature; // IFF chunk name + uint32 chunksize; // chunk size without header +}; +struct OKT_SAMPLE +{ + char name[20]; + uint32 length; // length in bytes + uint16 loopstart; // *2 for real value + uint16 looplen; // dito + uint16 volume; // default volume + uint16 type; // 7-/8-bit sample +}; -typedef struct OKTSAMPLE +STATIC_ASSERT(sizeof(OKT_SAMPLE) == 32); + +#pragma pack() + + +// just for keeping track of offsets and stuff... +struct OKT_SAMPLEINFO { - CHAR name[20]; - DWORD length; - WORD loopstart; - WORD looplen; - BYTE pad1; - BYTE volume; - BYTE pad2; - BYTE pad3; -} OKTSAMPLE; + DWORD start; // start position of the IFF block + DWORD length; // length of the IFF block +}; -bool CSoundFile::ReadOKT(const BYTE *lpStream, DWORD dwMemLength) -//--------------------------------------------------------------- +// Parse the sample header block +void Read_OKT_Samples(const BYTE *lpStream, const DWORD dwMemLength, vector<bool> &sample7bit, CSoundFile *pSndFile) +//------------------------------------------------------------------------------------------------------------------ { - OKTFILEHEADER *pfh = (OKTFILEHEADER *)lpStream; - DWORD dwMemPos = sizeof(OKTFILEHEADER); - UINT nsamples = 0, npatterns = 0, norders = 0; + pSndFile->m_nSamples = min((SAMPLEINDEX)(dwMemLength / 32), MAX_SAMPLES - 1); // typically 36 + sample7bit.resize(pSndFile->GetNumSamples()); - if ((!lpStream) || (dwMemLength < 1024)) return false; - if ((pfh->okta != 0x41544B4F) || (pfh->song != 0x474E4F53) - || (pfh->cmod != 0x444F4D43) || (pfh->chnsetup[0]) || (pfh->chnsetup[2]) - || (pfh->chnsetup[4]) || (pfh->chnsetup[6]) || (pfh->fixed8 != 0x08000000) - || (pfh->samp != 0x504D4153)) return false; - m_nType = MOD_TYPE_OKT; - m_nChannels = 4 + pfh->chnsetup[1] + pfh->chnsetup[3] + pfh->chnsetup[5] + pfh->chnsetup[7]; - if (m_nChannels > MAX_CHANNELS) m_nChannels = MAX_CHANNELS; - nsamples = BigEndian(pfh->samplen) >> 5; - m_nSamples = nsamples; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - // Reading samples - for (UINT smp=1; smp <= nsamples; smp++) + for(SAMPLEINDEX nSmp = 1; nSmp <= pSndFile->GetNumSamples(); nSmp++) { - if (dwMemPos >= dwMemLength) return true; - if (smp < MAX_SAMPLES) + MODSAMPLE *pSmp = &pSndFile->Samples[nSmp]; + OKT_SAMPLE oktsmp; + memcpy(&oktsmp, lpStream + (nSmp - 1) * 32, sizeof(OKT_SAMPLE)); + + oktsmp.length = min(BigEndian(oktsmp.length), MAX_SAMPLE_LENGTH); + oktsmp.loopstart = BigEndianW(oktsmp.loopstart) * 2; + oktsmp.looplen = BigEndianW(oktsmp.looplen) * 2; + oktsmp.volume = BigEndianW(oktsmp.volume); + oktsmp.type = BigEndianW(oktsmp.type); + + MemsetZero(*pSmp); + strncpy(pSndFile->m_szNames[nSmp], oktsmp.name, 20); + SpaceToNullStringFixed(pSndFile->m_szNames[nSmp], 20); + + pSmp->nC5Speed = 8287; + pSmp->nGlobalVol = 64; + pSmp->nVolume = min(oktsmp.volume, 64) * 4; + pSmp->nLength = oktsmp.length & ~1; // round down + // parse loops + if (oktsmp.looplen > 2 && ((UINT)oktsmp.loopstart) + ((UINT)oktsmp.looplen) <= pSmp->nLength) { - OKTSAMPLE *psmp = (OKTSAMPLE *)(lpStream + dwMemPos); - MODSAMPLE *pSmp = &Samples[smp]; - - memcpy(m_szNames[smp], psmp->name, 20); - SpaceToNullStringFixed(m_szNames[smp], 20); - pSmp->uFlags = 0; - pSmp->nLength = BigEndian(psmp->length) & ~1; - pSmp->nLoopStart = BigEndianW(psmp->loopstart); - pSmp->nLoopEnd = pSmp->nLoopStart + BigEndianW(psmp->looplen); - if (pSmp->nLoopStart + 2 < pSmp->nLoopEnd) pSmp->uFlags |= CHN_LOOP; - pSmp->nGlobalVol = 64; - pSmp->nVolume = psmp->volume << 2; - pSmp->nC5Speed = 8363; + pSmp->nSustainStart = oktsmp.loopstart; + pSmp->nSustainEnd = oktsmp.loopstart + oktsmp.looplen; + if (pSmp->nSustainStart < pSmp->nLength && pSmp->nSustainEnd <= pSmp->nLength) + pSmp->uFlags |= CHN_SUSTAINLOOP; + else + pSmp->nSustainStart = pSmp->nSustainEnd = 0; } - dwMemPos += sizeof(OKTSAMPLE); + sample7bit[nSmp - 1] = (oktsmp.type == 0 || oktsmp.type == 2) ? true : false; } - // SPEE - if (dwMemPos >= dwMemLength) return true; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x45455053) +} + + +// Parse a pattern block +void Read_OKT_Pattern(const BYTE *lpStream, const DWORD dwMemLength, const PATTERNINDEX nPat, CSoundFile *pSndFile) +//----------------------------------------------------------------------------------------------------------------- +{ + #define ASSERT_CAN_READ(x) \ + if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return; + + DWORD dwMemPos = 0; + + ASSERT_CAN_READ(2); + ROWINDEX nRows = CLAMP(BigEndianW(*(uint16 *)(lpStream + dwMemPos)), 1, MAX_PATTERN_ROWS); + dwMemPos += 2; + + if(pSndFile->Patterns.Insert(nPat, nRows)) + return; + + const CHANNELINDEX nChns = pSndFile->GetNumChannels(); + MODCOMMAND *mrow = pSndFile->Patterns[nPat], *m; + + for(ROWINDEX nRow = 0; nRow < nRows; nRow++, mrow += nChns) { - m_nDefaultSpeed = lpStream[dwMemPos+9]; - dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // SLEN - if (dwMemPos >= dwMemLength) return true; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C53) - { - npatterns = lpStream[dwMemPos+9]; - dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PLEN - if (dwMemPos >= dwMemLength) return true; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x4E454C50) - { - norders = lpStream[dwMemPos+9]; - dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PATT - if (dwMemPos >= dwMemLength) return true; - if (*((DWORD *)(lpStream + dwMemPos)) == 0x54544150) - { - UINT orderlen = norders; - if (orderlen >= MAX_ORDERS) orderlen = MAX_ORDERS-1; - Order.resize(orderlen); - for (UINT i=0; i<orderlen; i++) Order[i] = lpStream[dwMemPos+10+i]; - for (UINT j=orderlen; j>1; j--) { if (Order[j-1]) break; Order[j-1] = 0xFF; } - dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - } - // PBOD - UINT npat = 0; - while ((dwMemPos < dwMemLength-10) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4250)) - { - DWORD dwPos = dwMemPos + 10; - UINT rows = lpStream[dwMemPos+9]; - if (!rows) rows = 64; - if (npat < MAX_PATTERNS) + m = mrow; + for(CHANNELINDEX nChn = 0; nChn < nChns; nChn++, m++) { - if(Patterns.Insert(npat, rows)) - return true; - MODCOMMAND *m = Patterns[npat]; - UINT imax = m_nChannels*rows; - for (UINT i=0; i<imax; i++, m++, dwPos+=4) + ASSERT_CAN_READ(4); + m->note = lpStream[dwMemPos++]; + m->instr = lpStream[dwMemPos++]; + int8 fxcmd = lpStream[dwMemPos++]; + m->param = lpStream[dwMemPos++]; + + if(m->note > 0 && m->note <= 36) { - if (dwPos+4 > dwMemLength) break; - const BYTE *p = lpStream+dwPos; - UINT note = p[0]; - if (note) + m->note += 48; + m->instr++; + } else + { + m->instr = 0; + } + + switch(fxcmd) + { + case 0: // Nothing + m->param = 0; + break; + + case 1: // 1 Portamento Down (Period) + m->command = CMD_PORTAMENTODOWN; + m->param &= 0x0F; + break; + case 2: // 2 Portamento Up (Period) + m->command = CMD_PORTAMENTOUP; + m->param &= 0x0F; + break; + +#if 0 + /* these aren't like Jxx: "down" means to *subtract* the offset from the note. + For now I'm going to leave these unimplemented. */ + case 10: // A Arpeggio 1 (down, orig, up) + case 11: // B Arpeggio 2 (orig, up, orig, down) + if (note->param) + note->command = CMD_ARPEGGIO; + break; +#endif + // This one is close enough to "standard" arpeggio -- I think! + case 12: // C Arpeggio 3 (up, up, orig) + if (m->param) + m->command = CMD_ARPEGGIO; + break; + + case 13: // D Slide Down (Notes) + if (m->param) { - m->note = note + 48; - m->instr = p[1] + 1; + m->command = CMD_NOTESLIDEDOWN; + m->param = 0x10 | min(0x0F, m->param); } - UINT command = p[2]; - UINT param = p[3]; - m->param = param; - switch(command) + break; + case 30: // U Slide Up (Notes) + if (m->param) { - // 0: no effect - case 0: + m->command = CMD_NOTESLIDEUP; + m->param = 0x10 | min(0x0F, m->param); + } + break; + /* We don't have fine note slide, but this is supposed to happen once + per row. Sliding every 5 (non-note) ticks kind of works (at least at + speed 6), but implementing fine slides would of course be better. */ + case 21: // L Slide Down Once (Notes) + if (m->param) + { + m->command = CMD_NOTESLIDEDOWN; + m->param = 0x50 | min(0x0F, m->param); + } + break; + case 17: // H Slide Up Once (Notes) + if (m->param) + { + m->command = CMD_NOTESLIDEUP; + m->param = 0x50 | min(0x0F, m->param); + } + break; + + case 15: // F Set Filter <>00:ON + // Not implemented, but let's import it anyway... + m->command = CMD_MODCMDEX; + m->param = !!m->param; + break; + + case 25: // P Pos Jump + m->command = CMD_POSITIONJUMP; + break; + + case 27: // R Release sample (apparently not listed in the help!) + m->Clear(); + m->note = NOTE_KEYOFF; + break; + + case 28: // S Speed + m->command = CMD_SPEED; // or tempo? + break; + + case 31: // V Volume + m->command = CMD_VOLUMESLIDE; + switch (m->param >> 4) + { + case 4: + if (m->param != 0x40) + { + m->param &= 0x0F; // D0x + break; + } + // 0x40 is set volume -- fall through + case 0: case 1: case 2: case 3: + m->volcmd = VOLCMD_VOLUME; + m->vol = m->param; + m->command = CMD_NONE; + m->param = 0; break; - // 1: Portamento Up - case 1: - case 17: - case 30: - if (param) m->command = CMD_PORTAMENTOUP; + case 5: + m->param = (m->param & 0x0F) << 4; // Dx0 break; - // 2: Portamento Down - case 2: - case 13: - case 21: - if (param) m->command = CMD_PORTAMENTODOWN; + case 6: + m->param = 0xF0 | min(m->param & 0x0F, 0x0E); // DFx break; - // 10: Arpeggio - case 10: - case 11: - case 12: - m->command = CMD_ARPEGGIO; + case 7: + m->param = (min(m->param & 0x0F, 0x0E) << 4) | 0x0F; // DxF break; - // 15: Filter - case 15: - m->command = CMD_MODCMDEX; - m->param = param & 0x0F; + default: + // Junk. + m->command = m->param = 0; break; - // 25: Position Jump - case 25: - m->command = CMD_POSITIONJUMP; - break; - // 28: Set Speed - case 28: - m->command = CMD_SPEED; - break; - // 31: Volume Control - case 31: - if (param <= 0x40) m->command = CMD_VOLUME; else - if (param <= 0x50) { m->command = CMD_VOLUMESLIDE; m->param &= 0x0F; if (!m->param) m->param = 0x0F; } else - if (param <= 0x60) { m->command = CMD_VOLUMESLIDE; m->param = (param & 0x0F) << 4; if (!m->param) m->param = 0xF0; } else - if (param <= 0x70) { m->command = CMD_MODCMDEX; m->param = 0xB0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xBF; } else - if (param <= 0x80) { m->command = CMD_MODCMDEX; m->param = 0xA0 | (param & 0x0F); if (!(param & 0x0F)) m->param = 0xAF; } - break; } + break; + +#if 0 + case 24: // O Old Volume (???) + m->command = CMD_VOLUMESLIDE; + m->param = 0; + break; +#endif + + default: + m->command = m->param = 0; + //ASSERT(false); + break; } } - npat++; - dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; } - // SBOD - UINT nsmp = 1; - while ((dwMemPos < dwMemLength - 10) && (*((DWORD *)(lpStream + dwMemPos)) == 0x444F4253)) + + #undef ASSERT_CAN_READ +} + + +bool CSoundFile::ReadOKT(const BYTE *lpStream, const DWORD dwMemLength) +//--------------------------------------------------------------------- +{ + #define ASSERT_CAN_READ(x) \ + if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; + + DWORD dwMemPos = 0; + + ASSERT_CAN_READ(8); + if (memcmp(lpStream, "OKTASONG", 8) != 0) + return false; + dwMemPos += 8; + + OKT_IFFCHUNK iffHead; + // prepare some arrays to store offsets etc. + vector<DWORD> patternOffsets; + vector<bool> sample7bit; // 7-/8-bit sample + vector<OKT_SAMPLEINFO> samplePos; + PATTERNINDEX nPatterns = 0; + ORDERINDEX nOrders = 0; + + MemsetZero(m_szNames); + m_nChannels = 0; + m_nSamples = 0; + + // Go through IFF chunks... + while(dwMemPos < dwMemLength) { - if (nsmp < MAX_SAMPLES) ReadSample(&Samples[nsmp], RS_PCM8S, (LPSTR)(lpStream+dwMemPos+8), dwMemLength-dwMemPos-8); - dwMemPos += BigEndian(*((DWORD *)(lpStream + dwMemPos + 4))) + 8; - nsmp++; + ASSERT_CAN_READ(sizeof(OKT_IFFCHUNK)); + memcpy(&iffHead, lpStream + dwMemPos, sizeof(OKT_IFFCHUNK)); + iffHead.signature = BigEndian(iffHead.signature); + iffHead.chunksize = BigEndian(iffHead.chunksize); + dwMemPos += sizeof(OKT_IFFCHUNK); + + switch(iffHead.signature) + { + case OKTCHUNKID_CMOD: + // read that weird channel setup table + if(m_nChannels > 0) + break; + ASSERT_CAN_READ(8); + for(CHANNELINDEX nChn = 0; nChn < 4; nChn++) + { + if(lpStream[dwMemPos + nChn * 2] || lpStream[dwMemPos + nChn * 2 + 1]) + { + ChnSettings[m_nChannels++].nPan = (((nChn & 3) == 1) || ((nChn & 3) == 2)) ? 0xC0 : 0x40; + } + ChnSettings[m_nChannels++].nPan = (((nChn & 3) == 1) || ((nChn & 3) == 2)) ? 0xC0 : 0x40; + } + break; + + case OKTCHUNKID_SAMP: + // convert sample headers + if(m_nSamples > 0) + break; + ASSERT_CAN_READ(iffHead.chunksize); + Read_OKT_Samples(lpStream + dwMemPos, iffHead.chunksize, sample7bit, this); + break; + + case OKTCHUNKID_SPEE: + // read default speed + { + ASSERT_CAN_READ(2); + uint16 defspeed = BigEndianW(*((uint16 *)(lpStream + dwMemPos))); + m_nDefaultSpeed = CLAMP(defspeed, 1, 255); + } + break; + + case OKTCHUNKID_SLEN: + // number of patterns, we don't need this. + break; + + case OKTCHUNKID_PLEN: + // read number of valid orders + ASSERT_CAN_READ(2); + nOrders = BigEndianW(*((uint16 *)(lpStream + dwMemPos))); + break; + + case OKTCHUNKID_PATT: + // read the orderlist + ASSERT_CAN_READ(iffHead.chunksize); + Order.ReadAsByte(lpStream + dwMemPos, min(iffHead.chunksize, MAX_ORDERS), iffHead.chunksize); + break; + + case OKTCHUNKID_PBOD: + // don't read patterns for now, as the number of channels might be unknown at this point. + if(nPatterns < MAX_PATTERNS) + { + if(iffHead.chunksize > 0) + patternOffsets.push_back(dwMemPos); + nPatterns++; + } + break; + + case OKTCHUNKID_SBOD: + // sample data - same as with patterns, as we need to know the sample format / length + if(samplePos.size() < MAX_SAMPLES - 1) + { + ASSERT_CAN_READ(iffHead.chunksize); + if(iffHead.chunksize) + { + OKT_SAMPLEINFO sinfo; + sinfo.start = dwMemPos; + sinfo.length = iffHead.chunksize; + samplePos.push_back(sinfo); + } + } + break; + } + + dwMemPos += iffHead.chunksize; } + + // If there wasn't even a CMOD chunk, we can't really load this. + if(m_nChannels == 0) + return false; + + m_nDefaultTempo = 125; + m_nDefaultGlobalVolume = 256; + m_nSamplePreAmp = m_nVSTiVolume = 48; + m_nType = MOD_TYPE_OKT; + m_nMinPeriod = 0x71 << 2; + m_nMaxPeriod = 0x358 << 2; + + // Fix orderlist + for(ORDERINDEX nOrd = nOrders; nOrd < Order.GetLengthTailTrimmed(); nOrd++) + { + Order[nOrd] = Order.GetInvalidPatIndex(); + } + + // Read patterns + for(PATTERNINDEX nPat = 0; nPat < nPatterns; nPat++) + { + if(patternOffsets[nPat] > 0) + Read_OKT_Pattern(lpStream + patternOffsets[nPat], dwMemLength - patternOffsets[nPat], nPat, this); + else + Patterns.Insert(nPat, 64); // invent empty pattern + } + + // Read samples + size_t nFileSmp = 0; + for(SAMPLEINDEX nSmp = 1; nSmp < m_nSamples; nSmp++) + { + if(nFileSmp >= samplePos.size()) + break; + + MODSAMPLE *pSmp = &Samples[nSmp]; + if(pSmp->nLength == 0) + continue; + + // weird stuff? + if(pSmp->nLength != samplePos[nFileSmp].length) + { + pSmp->nLength = min(pSmp->nLength, samplePos[nFileSmp].length); + } + + ReadSample(pSmp, RS_PCM8S, (LPCSTR)(lpStream + samplePos[nFileSmp].start), dwMemLength - samplePos[nFileSmp].start); + + // 7-bit to 8-bit hack + if(sample7bit[nSmp - 1] && pSmp->pSample) + { + for(size_t i = 0; i < pSmp->nLength; i++) + pSmp->pSample[i] = CLAMP(pSmp->pSample[i] * 2, -128, 127); + } + + nFileSmp++; + } + + SetModFlag(MSF_COMPATIBLE_PLAY, true); + return true; + + #undef ASSERT_CAN_READ } - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-10 17:35:53
|
Revision: 639 http://modplug.svn.sourceforge.net/modplug/?rev=639&view=rev Author: saga-games Date: 2010-07-10 17:35:43 +0000 (Sat, 10 Jul 2010) Log Message: ----------- [Fix] OKT Loader: Files were not converted to IT, although this should be done with the new loader. [Fix] MTM Loader: The "beats per track" (means lines per pattern) setting is now taken into account. [Mod] OpenMPT: Version is now 1.18.02.03 [Ref] More documentation in Sndfile.h! [Ref] Adding some const to that ungzip loader. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Load_mtm.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/ungzip/ungzip.cpp trunk/OpenMPT/ungzip/ungzip.h Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-10 17:35:43 UTC (rev 639) @@ -347,7 +347,6 @@ m_SndFile.ChangeModTypeTo(MOD_TYPE_MOD); break; case MOD_TYPE_MED: - case MOD_TYPE_OKT: case MOD_TYPE_AMS: m_SndFile.ChangeModTypeTo(MOD_TYPE_XM); if ((m_SndFile.m_nDefaultTempo == 125) && (m_SndFile.m_nDefaultSpeed == 6) && (!m_SndFile.m_nInstruments)) @@ -358,9 +357,6 @@ m_SndFile.m_nType = MOD_TYPE_XM; } break; - case MOD_TYPE_MT2: - m_SndFile.ChangeModTypeTo(MOD_TYPE_IT); - break; case MOD_TYPE_FAR: case MOD_TYPE_PTM: case MOD_TYPE_STM: @@ -370,6 +366,8 @@ break; case MOD_TYPE_PSM: case MOD_TYPE_ULT: + case MOD_TYPE_OKT: + case MOD_TYPE_MT2: default: m_SndFile.ChangeModTypeTo(MOD_TYPE_IT); } Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/mptrack/version.h 2010-07-10 17:35:43 UTC (rev 639) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 #define VER_MINOR 02 -#define VER_MINORMINOR 02 +#define VER_MINORMINOR 03 //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_mtm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-07-10 17:35:43 UTC (rev 639) @@ -4,14 +4,13 @@ * Copied to OpenMPT from libmodplug. * * Authors: Olivier Lapicque <oli...@jp...> - * + * OpenMPT Devs + * */ #include "stdafx.h" #include "sndfile.h" -#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" - ////////////////////////////////////////////////////////// // MTM file support (import only) @@ -19,29 +18,30 @@ typedef struct tagMTMSAMPLE { - char samplename[22]; - DWORD length; - DWORD reppos; - DWORD repend; - CHAR finetune; - BYTE volume; - BYTE attribute; + char samplename[22]; + uint32 length; + uint32 reppos; + uint32 repend; + int8 finetune; + uint8 volume; + uint8 attribute; } MTMSAMPLE; typedef struct tagMTMHEADER { - 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) - WORD commentsize; // length of comment field - BYTE numsamples; // number of samples saved - BYTE attribute; // attribute byte (unused) - BYTE beatspertrack; - BYTE numchannels; // number of channels used - BYTE panpos[32]; // voice pan positions + char id[3]; // MTM file marker + uint8 version; // Tracker version + char songname[20]; // ASCIIZ songname + uint16 numtracks; // number of tracks saved + uint8 lastpattern; // last pattern number saved + uint8 lastorder; // last order number to play (songlength-1) + uint16 commentsize; // length of comment field + uint8 numsamples; // number of samples saved + uint8 attribute; // attribute byte (unused) + uint8 beatspertrack; // numbers of rows in every pattern + uint8 numchannels; // number of channels used + uint8 panpos[32]; // channel pan positions } MTMHEADER; @@ -51,11 +51,12 @@ bool CSoundFile::ReadMTM(LPCBYTE lpStream, DWORD dwMemLength) //----------------------------------------------------------- { - MTMHEADER *pmh = (MTMHEADER *)lpStream; DWORD dwMemPos = 66; if ((!lpStream) || (dwMemLength < 0x100)) return false; - if ((strncmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32) + + MTMHEADER *pmh = (MTMHEADER *)lpStream; + if ((memcmp(pmh->id, "MTM", 3)) || (pmh->numchannels > 32) || (pmh->numsamples >= MAX_SAMPLES) || (!pmh->numsamples) || (!pmh->numtracks) || (!pmh->numchannels) || (!pmh->lastpattern) || (pmh->lastpattern > MAX_PATTERNS)) return false; @@ -75,8 +76,8 @@ SpaceToNullStringFixed(m_szNames[i], 22); Samples[i].nVolume = pms->volume << 2; Samples[i].nGlobalVol = 64; - DWORD len = pms->length; - if ((len > 4) && (len <= MAX_SAMPLE_LENGTH)) + UINT len = pms->length; + if ((len > 2) && (len <= MAX_SAMPLE_LENGTH)) { Samples[i].nLength = len; Samples[i].nLoopStart = pms->reppos; @@ -97,31 +98,32 @@ dwMemPos += 37; } // Setting Channel Pan Position - for (UINT ich=0; ich<m_nChannels; ich++) + for (CHANNELINDEX ich = 0; ich < m_nChannels; ich++) { ChnSettings[ich].nPan = ((pmh->panpos[ich] & 0x0F) << 4) + 8; ChnSettings[ich].nVolume = 64; } // Reading pattern order - Order.ReadAsByte(lpStream+dwMemPos, pmh->lastorder+1, dwMemLength-dwMemPos); + Order.ReadAsByte(lpStream + dwMemPos, pmh->lastorder + 1, dwMemLength - dwMemPos); dwMemPos += 128; // Reading Patterns + ROWINDEX nPatRows = CLAMP(pmh->beatspertrack, 1, MAX_PATTERN_ROWS); LPCBYTE pTracks = lpStream + dwMemPos; dwMemPos += 192 * pmh->numtracks; LPWORD pSeq = (LPWORD)(lpStream + dwMemPos); - for (UINT pat=0; pat<=pmh->lastpattern; pat++) + for (PATTERNINDEX pat = 0; pat <= pmh->lastpattern; pat++) { - if(Patterns.Insert(pat, 64)) break; + if(Patterns.Insert(pat, nPatRows)) break; for (UINT n=0; n<32; n++) if ((pSeq[n]) && (pSeq[n] <= pmh->numtracks) && (n < m_nChannels)) { LPCBYTE p = pTracks + 192 * (pSeq[n]-1); MODCOMMAND *m = Patterns[pat] + n; - for (UINT i=0; i<64; i++, m+=m_nChannels, p+=3) + for (UINT i = 0; i < nPatRows; i++, m += m_nChannels, p += 3) { if (p[0] & 0xFC) m->note = (p[0] >> 2) + 37; m->instr = ((p[0] & 0x03) << 4) | (p[1] >> 4); - UINT cmd = p[1] & 0x0F; - UINT param = p[2]; + uint8 cmd = p[1] & 0x0F; + uint8 param = p[2]; if (cmd == 0x0A) { if (param & 0xF0) param &= 0xF0; else param &= 0x0F; @@ -133,7 +135,7 @@ } pSeq += 32; } - dwMemPos += 64*(pmh->lastpattern+1); + dwMemPos += 64 * (pmh->lastpattern + 1); if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) { UINT n = pmh->commentsize; @@ -146,7 +148,7 @@ { if (!m_lpszSongComments[i]) { - m_lpszSongComments[i] = ((i+1) % 40) ? 0x20 : 0x0D; + m_lpszSongComments[i] = ((i + 1) % 40) ? 0x20 : 0x0D; } } } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-10 17:35:43 UTC (rev 639) @@ -1437,7 +1437,7 @@ { if ((!m_nSamples) || (!m_nChannels)) return MOD_TYPE_NONE; if (!m_nType) return MOD_TYPE_NONE; - if (m_nType & (MOD_TYPE_MOD|MOD_TYPE_OKT)) + if (m_nType & (MOD_TYPE_MOD/*|MOD_TYPE_OKT*/)) return MOD_TYPE_MOD; if (m_nType & (MOD_TYPE_S3M|MOD_TYPE_STM|MOD_TYPE_ULT|MOD_TYPE_FAR|MOD_TYPE_PTM)) return MOD_TYPE_S3M; Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-10 17:35:43 UTC (rev 639) @@ -26,22 +26,21 @@ // Sample Struct struct MODSAMPLE { - UINT nLength,nLoopStart,nLoopEnd; - //nLength <-> Number of 'frames'? - UINT nSustainStart, nSustainEnd; - LPSTR pSample; - UINT nC5Speed; - WORD nPan; - WORD nVolume; - WORD nGlobalVol; - WORD uFlags; - signed char RelativeTone; - signed char nFineTune; - BYTE nVibType; - BYTE nVibSweep; - BYTE nVibDepth; - BYTE nVibRate; - CHAR name[32]; + UINT nLength, nLoopStart, nLoopEnd; // In samples, not bytes + UINT nSustainStart, nSustainEnd; // Dito + LPSTR pSample; // Pointer to sample data + UINT nC5Speed; // Frequency of middle c, in Hz (for IT/S3M/MPTM) + WORD nPan; // Default sample panning (if pan flag is set) + WORD nVolume; // Default volume + WORD nGlobalVol; // Global volume (sample volume is multiplied by this) + WORD uFlags; // Sample flags + signed char RelativeTone; // Relative note to middle c (for MOD/XM) + signed char nFineTune; // Finetune period (for MOD/XM) + BYTE nVibType; // Auto vibrato type + BYTE nVibSweep; // Auto vibrato sweep (i.e. how long it takes until the vibrato effect reaches its full strength) + BYTE nVibDepth; // Auto vibrato depth + BYTE nVibRate; // Auto vibrato rate (speed) + //CHAR name[32]; // Maybe it would be nicer to have sample names here, but that would require some refactoring. Also, would this slow down the mixer (cache misses)? CHAR filename[MAX_SAMPLEFILENAME]; // Return the size of one (elementary) sample in bytes. @@ -90,53 +89,53 @@ // Instrument Struct struct MODINSTRUMENT { - UINT nFadeOut; - DWORD dwFlags; - UINT nGlobalVol; - UINT nPan; + UINT nFadeOut; // Instrument fadeout speed + DWORD dwFlags; // Instrument flags + UINT nGlobalVol; // Global volume (all sample volumes are multiplied with this) + UINT nPan; // Default pan (overrides sample panning), if the appropriate flag is set - INSTRUMENTENVELOPE VolEnv; - INSTRUMENTENVELOPE PanEnv; - INSTRUMENTENVELOPE PitchEnv; + INSTRUMENTENVELOPE VolEnv; // Volume envelope data + INSTRUMENTENVELOPE PanEnv; // Panning envelope data + INSTRUMENTENVELOPE PitchEnv; // Pitch / filter envelope data BYTE NoteMap[128]; // Note mapping, f.e. C-5 => D-5 WORD Keyboard[128]; // Sample mapping, f.e. C-5 => Sample 1 - BYTE nNNA; - BYTE nDCT; - BYTE nDNA; - BYTE nPanSwing; - BYTE nVolSwing; - BYTE nIFC; - BYTE nIFR; + BYTE nNNA; // New note action + BYTE nDCT; // Duplicate check type (i.e. which condition will trigger the duplicate note action) + BYTE nDNA; // Duplicate note action + BYTE nPanSwing; // Random panning factor + BYTE nVolSwing; // Random volume factor + BYTE nIFC; // Default filter cutoff + BYTE nIFR; // Default filter resonance - WORD wMidiBank; - BYTE nMidiProgram; - BYTE nMidiChannel; - BYTE nMidiDrumKey; - signed char nPPS; //Pitch to Pan Separator? - unsigned char nPPC; //Pitch Centre? + WORD wMidiBank; // MIDI bank + BYTE nMidiProgram; // MIDI program + BYTE nMidiChannel; // MIDI channel + BYTE nMidiDrumKey; // Drum set note mapping (currently only used by the .MID loader) + signed char nPPS; //Pitch/Pan separation (i.e. how wide the panning spreads) + unsigned char nPPC; //Pitch/Pan centre CHAR name[32]; // Note: not guaranteed to be null-terminated. CHAR filename[32]; - PLUGINDEX nMixPlug; //rewbs.instroVSTi + PLUGINDEX nMixPlug; // Plugin assigned to this instrument // -> CODE#0027 // -> DESC="per-instrument volume ramping setup (refered as attack)" - USHORT nVolRamp; + USHORT nVolRamp; // Default sample ramping // -! NEW_FEATURE#0027 - UINT nResampling; - BYTE nCutSwing; - BYTE nResSwing; - BYTE nFilterMode; - WORD wPitchToTempoLock; - BYTE nPluginVelocityHandling; - BYTE nPluginVolumeHandling; + UINT nResampling; // Resampling mode + BYTE nCutSwing; // Random cutoff factor + BYTE nResSwing; // Random resonance factor + BYTE nFilterMode; // Default filter mode + WORD wPitchToTempoLock; // BPM at which the samples assigned to this instrument loop correctly + BYTE nPluginVelocityHandling; // How to deal with plugin velocity + BYTE nPluginVolumeHandling; // How to deal with plugin volume // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // WHEN adding new members here, ALSO update Sndfile.cpp (instructions near the top of this file)! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - CTuning* pTuning; + CTuning* pTuning; // sample tuning assigned to this instrument static CTuning* s_DefaultTuning; void SetTuning(CTuning* pT) @@ -575,7 +574,7 @@ m_nGlobalVolumeDestination, m_nSamplePreAmp, m_nVSTiVolume; long m_lHighResRampingGlobalVolume; UINT m_nFreqFactor, m_nTempoFactor, m_nOldGlbVolSlide; - LONG m_nMinPeriod, m_nMaxPeriod; + LONG m_nMinPeriod, m_nMaxPeriod; // min period = highest possible frequency, max period = lowest possible frequency LONG m_nRepeatCount; // -1 means repeat infinitely. DWORD m_nGlobalFadeSamples, m_nGlobalFadeMaxSamples; UINT m_nMaxOrderPosition, m_nPatternNames; @@ -592,7 +591,7 @@ MODMIDICFG m_MidiCfg; // Midi macro config table SNDMIXPLUGIN m_MixPlugins[MAX_MIXPLUGINS]; // Mix plugins SNDMIXSONGEQ m_SongEQ; // Default song EQ preset - CHAR CompressionTable[16]; + CHAR CompressionTable[16]; // ADPCM compression LUT bool m_bChannelMuteTogglePending[MAX_BASECHANNELS]; CSoundFilePlayConfig* m_pConfig; @@ -620,11 +619,6 @@ inline bool TypeIsMOD_S3M() const {return (m_nType & (MOD_TYPE_MOD | MOD_TYPE_S3M)) != 0;} CModDoc* GetpModDoc() {return m_pModDoc;} - - //Return the number of channels in the pattern. In 1.17.02.45 - //it returned the number of channels with volume != 0 - CHANNELINDEX GetNumChannels() const {return static_cast<CHANNELINDEX>(m_nChannels);} - void SetMasterVolume(UINT vol, bool adjustAGC = false); UINT GetMasterVolume() const { return m_nMasterVolume; } PATTERNINDEX GetNumPatterns() const; @@ -636,6 +630,7 @@ UINT GetSongComments(LPSTR s, UINT cbsize, UINT linesize=32); UINT GetRawSongComments(LPSTR s, UINT cbsize, UINT linesize=32); UINT GetMaxPosition() const; + CHANNELINDEX GetNumChannels() const { return m_nChannels; } IMixPlugin* GetInstrumentPlugin(INSTRUMENTINDEX instr); const CModSpecifications& GetModSpecifications() const {return *m_pModSpecs;} Modified: trunk/OpenMPT/ungzip/ungzip.cpp =================================================================== --- trunk/OpenMPT/ungzip/ungzip.cpp 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/ungzip/ungzip.cpp 2010-07-10 17:35:43 UTC (rev 639) @@ -30,8 +30,8 @@ } -bool CGzipArchive::IsArchive() -//---------------------------- +bool CGzipArchive::IsArchive() const +//---------------------------------- { if(m_lpStream == nullptr || m_dwStreamLen <= (sizeof(GZheader) + sizeof(GZtrailer))) return false; Modified: trunk/OpenMPT/ungzip/ungzip.h =================================================================== --- trunk/OpenMPT/ungzip/ungzip.h 2010-07-10 13:37:44 UTC (rev 638) +++ trunk/OpenMPT/ungzip/ungzip.h 2010-07-10 17:35:43 UTC (rev 639) @@ -56,7 +56,7 @@ LPBYTE GetOutputFile() const { return m_pOutputFile; } DWORD GetOutputFileLength() const { return m_dwOutputLen; } - bool IsArchive(); + bool IsArchive() const; bool ExtractFile(); CGzipArchive(LPBYTE lpStream, DWORD dwMemLength); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-13 14:01:36
|
Revision: 643 http://modplug.svn.sourceforge.net/modplug/?rev=643&view=rev Author: saga-games Date: 2010-07-13 14:01:29 +0000 (Tue, 13 Jul 2010) Log Message: ----------- [Ref] Shuffled around some MODCOMMAND editing functions to new file modcommand.cpp. There might be more functions worth moving which I didn't think of. Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/soundlib/Sndfile.cpp Added Paths: ----------- trunk/OpenMPT/soundlib/modcommand.cpp Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2010-07-12 22:45:33 UTC (rev 642) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2010-07-13 14:01:29 UTC (rev 643) @@ -367,6 +367,9 @@ RelativePath="..\soundlib\mod_specifications.cpp"> </File> <File + RelativePath="..\soundlib\modcommand.cpp"> + </File> + <File RelativePath=".\Moddoc.cpp"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-07-12 22:45:33 UTC (rev 642) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-07-13 14:01:29 UTC (rev 643) @@ -493,6 +493,10 @@ > </File> <File + RelativePath="..\soundlib\modcommand.cpp" + > + </File> + <File RelativePath=".\Moddoc.cpp" > </File> Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-12 22:45:33 UTC (rev 642) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-13 14:01:29 UTC (rev 643) @@ -70,8 +70,6 @@ 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 @@ -457,7 +455,7 @@ m_nInstruments = 0; m_nPatternNames = 0; m_lpszPatternNames = NULL; - m_lpszSongComments = NULL; + m_lpszSongComments = nullptr; m_nFreqFactor = m_nTempoFactor = 128; m_nMasterVolume = 128; m_nMinPeriod = MIN_PERIOD; @@ -550,7 +548,7 @@ m_nPatternNames = 0; m_nMaxOrderPosition = 0; m_lpszPatternNames = NULL; - m_lpszSongComments = NULL; + m_lpszSongComments = nullptr; m_nMixLevels = mixLevels_original; // Will be overridden if appropriate. memset(Samples, 0, sizeof(Samples)); memset(ChnMix, 0, sizeof(ChnMix)); @@ -3028,7 +3026,6 @@ } - long CSoundFile::GetSampleOffset() //------------------------------- { @@ -3144,158 +3141,6 @@ } -/* 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 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). 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) -*/ -bool CSoundFile::TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn, bool bAllowMultipleEffects, bool bAllowNextRow, bool bRetry) -//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -{ - // NOTE: Effect remapping is only implemented for a few basic effects. - CHANNELINDEX nScanChnMin = nChn, nScanChnMax = nChn; - MODCOMMAND *p = Patterns[nPat], *m; - - // Scan all channels - if(nChn == CHANNELINDEX_INVALID) - { - nScanChnMin = 0; - nScanChnMax = m_nChannels - 1; - } - - // Scan channel(s) for same effect type - if an effect of the same type is already present, exit. - if(!bAllowMultipleEffects) - { - for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++) - { - m = p + nRow * m_nChannels + i; - if(!bIsVolumeEffect && m->command == nEffect) - return true; - if(bIsVolumeEffect && m->volcmd == nEffect) - return true; - } - } - - // Easy case: check if there's some space left to put the effect somewhere - for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++) - { - m = p + nRow * m_nChannels + i; - if(!bIsVolumeEffect && m->command == CMD_NONE) - { - m->command = nEffect; - m->param = nParam; - return true; - } - if(bIsVolumeEffect && m->volcmd == VOLCMD_NONE) - { - m->volcmd = nEffect; - m->vol = nParam; - return true; - } - } - - // 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) - { - // Move some effects that also work in the volume column, so there's place for our new effect. - if(!bIsVolumeEffect) - { - for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++) - { - m = p + nRow * m_nChannels + i; - switch(m->command) - { - case CMD_VOLUME: - m->volcmd = VOLCMD_VOLUME; - m->vol = m->param; - m->command = nEffect; - m->param = nParam; - return true; - - case CMD_PANNING8: - if(m_nType & MOD_TYPE_S3M && nParam > 0x80) - break; - - m->volcmd = VOLCMD_PANNING; - m->command = nEffect; - - if(m_nType & MOD_TYPE_S3M) - { - m->vol = m->param >> 1; - } - else - { - m->vol = (m->param >> 2) + 1; - } - - m->param = nParam; - return true; - } - } - } - - // Let's try it again by writing into the "other" effect column. - BYTE nNewEffect = CMD_NONE; - if(bIsVolumeEffect) - { - switch(nEffect) - { - case VOLCMD_PANNING: - nNewEffect = CMD_PANNING8; - if(m_nType & MOD_TYPE_S3M) - nParam <<= 1; - else - nParam = min(nParam << 2, 0xFF); - break; - case VOLCMD_VOLUME: - nNewEffect = CMD_VOLUME; - break; - } - } else - { - switch(nEffect) - { - case CMD_PANNING8: - nNewEffect = VOLCMD_PANNING; - if(m_nType & MOD_TYPE_S3M) - { - if(nParam <= 0x80) - nParam >>= 1; - else - nNewEffect = CMD_NONE; - } - else - { - nParam = (nParam >> 2) + 1; - } - break; - case CMD_VOLUME: - nNewEffect = CMD_VOLUME; - break; - } - } - if(nNewEffect != CMD_NONE) - { - if(TryWriteEffect(nPat, nRow, nNewEffect, nParam, !bIsVolumeEffect, nChn, bAllowMultipleEffects, bAllowNextRow, false) == true) return true; - } - } - - // Try in the next row if possible (this may also happen if we already retried) - if(bAllowNextRow && (nRow + 1 < Patterns[nPat].GetNumRows())) - { - return TryWriteEffect(nPat, nRow + 1, nEffect, nParam, bIsVolumeEffect, nChn, bAllowMultipleEffects, bAllowNextRow, bRetry); - } - - return false; -} - - // 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) //------------------------------------------------ @@ -3312,749 +3157,3 @@ 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) -//------------------------------------------- -{ - if(m->command != CMD_MODCMDEX) return; - m->command = CMD_S3MCMDEX; - switch(m->param & 0xF0) - { - case 0x10: m->command = CMD_PORTAMENTOUP; m->param |= 0xF0; break; - case 0x20: m->command = CMD_PORTAMENTODOWN; m->param |= 0xF0; break; - case 0x30: m->param = (m->param & 0x0F) | 0x10; break; - case 0x40: m->param = (m->param & 0x03) | 0x30; break; - case 0x50: m->param = (m->param & 0x0F) | 0x20; break; - case 0x60: m->param = (m->param & 0x0F) | 0xB0; break; - case 0x70: m->param = (m->param & 0x03) | 0x40; break; - case 0x90: m->command = CMD_RETRIG; m->param = 0x80 | (m->param & 0x0F); break; - case 0xA0: if (m->param & 0x0F) { m->command = CMD_VOLUMESLIDE; m->param = (m->param << 4) | 0x0F; } else m->command = 0; break; - case 0xB0: if (m->param & 0x0F) { m->command = CMD_VOLUMESLIDE; m->param |= 0xF0; } else m->command = 0; break; - case 0xC0: if (m->param == 0xC0) { m->command = CMD_NONE; m->note = NOTE_NOTECUT; } // this does different things in IT and ST3 - case 0xD0: if (m->param == 0xD0) { m->command = CMD_NONE; } // dito - // rest are the same - } -} - - -// Convert an Sxx command (S3M) to Exx command (MOD) -void CSoundFile::S3MSxx2MODExx(MODCOMMAND *m) -//------------------------------------------- -{ - if(m->command != CMD_S3MCMDEX) return; - m->command = CMD_MODCMDEX; - switch(m->param & 0xF0) - { - case 0x10: m->param = (m->param & 0x0F) | 0x30; break; - case 0x20: m->param = (m->param & 0x0F) | 0x50; break; - case 0x30: m->param = (m->param & 0x0F) | 0x40; break; - case 0x40: m->param = (m->param & 0x0F) | 0x70; break; - case 0x50: - case 0x60: - case 0x70: if(((m->param & 0xF0) == 0x70) && ((m->param & 0x0F) > 0x0A)) { m->command = CMD_NONE; break; } // no pitch env in XM format - case 0x90: - case 0xA0: m->command = CMD_XFINEPORTAUPDOWN; break; - case 0xB0: m->param = (m->param & 0x0F) | 0x60; break; - // rest are the same - } -} - - -// Convert a mod command from one format to another. -void CSoundFile::ConvertCommand(MODCOMMAND *m, MODTYPE nOldType, MODTYPE nNewType) -//-------------------------------------------------------------------------------- -{ - // helper variables - const bool oldTypeIsMOD = (nOldType == MOD_TYPE_MOD), oldTypeIsXM = (nOldType == MOD_TYPE_XM), - oldTypeIsS3M = (nOldType == MOD_TYPE_S3M), oldTypeIsIT = (nOldType == MOD_TYPE_IT), - oldTypeIsMPT = (nOldType == MOD_TYPE_MPT), oldTypeIsMOD_XM = (oldTypeIsMOD || oldTypeIsXM), - oldTypeIsS3M_IT_MPT = (oldTypeIsS3M || oldTypeIsIT || oldTypeIsMPT), - oldTypeIsIT_MPT = (oldTypeIsIT || oldTypeIsMPT); - - const bool newTypeIsMOD = (nNewType == MOD_TYPE_MOD), newTypeIsXM = (nNewType == MOD_TYPE_XM), - newTypeIsS3M = (nNewType == MOD_TYPE_S3M), newTypeIsIT = (nNewType == MOD_TYPE_IT), - newTypeIsMPT = (nNewType == MOD_TYPE_MPT), newTypeIsMOD_XM = (newTypeIsMOD || newTypeIsXM), - newTypeIsS3M_IT_MPT = (newTypeIsS3M || newTypeIsIT || newTypeIsMPT), - newTypeIsIT_MPT = (newTypeIsIT || newTypeIsMPT); - - ////////////////////////// - // Convert 8-bit Panning - if(m->command == CMD_PANNING8) - { - if(newTypeIsS3M) - { - m->param = (m->param + 1) >> 1; - } - else if(oldTypeIsS3M) - { - if(m->param == 0xA4) - { - // surround remap - m->command = (nNewType & (MOD_TYPE_IT|MOD_TYPE_MPT)) ? CMD_S3MCMDEX : CMD_XFINEPORTAUPDOWN; - m->param = 0x91; - } - else - { - m->param = min(m->param << 1, 0xFF); - } - } - } // End if(m->command == CMD_PANNING8) - - /////////////////////////////////////////////////////////////////////////////////////// - // MPTM to anything: Convert param control, extended envelope control, note delay+cut - if(oldTypeIsMPT) - { - if(m->IsPcNote()) - { - m->param = (BYTE)(min(MODCOMMAND::maxColumnValue, m->GetValueEffectCol()) * 0x7F / MODCOMMAND::maxColumnValue); - m->command = (m->note == NOTE_PC) ? CMD_MIDI : CMD_SMOOTHMIDI; // might be removed later - m->volcmd = VOLCMD_NONE; - m->note = NOTE_NONE; - m->instr = 0; - } - - // adjust extended envelope control commands - if((m->command == CMD_S3MCMDEX) && ((m->param & 0xF0) == 0x70) && ((m->param & 0x0F) > 0x0C)) - { - m->param = 0x7C; - } - - if(m->command == CMD_DELAYCUT) - { - m->command = CMD_S3MCMDEX; // when converting to MOD/XM, this will be converted to CMD_MODCMDEX later - m->param = 0xD0 | (m->param >> 4); // preserve delay nibble. - } - } // End if(oldTypeIsMPT) - - ///////////////////////////////////////// - // Convert MOD / XM to S3M / IT / MPTM - if(oldTypeIsMOD_XM && newTypeIsS3M_IT_MPT) - { - switch(m->command) - { - case CMD_MODCMDEX: - MODExx2S3MSxx(m); - break; - case CMD_VOLUME: - if (!m->volcmd) - { - m->volcmd = VOLCMD_VOLUME; - m->vol = m->param; - if (m->vol > 0x40) m->vol = 0x40; - m->command = m->param = 0; - } - break; - case CMD_PORTAMENTOUP: - if (m->param > 0xDF) m->param = 0xDF; - break; - case CMD_PORTAMENTODOWN: - if (m->param > 0xDF) m->param = 0xDF; - break; - case CMD_XFINEPORTAUPDOWN: - switch(m->param & 0xF0) - { - case 0x10: m->command = CMD_PORTAMENTOUP; m->param = (m->param & 0x0F) | 0xE0; break; - case 0x20: m->command = CMD_PORTAMENTODOWN; m->param = (m->param & 0x0F) | 0xE0; break; - case 0x50: - case 0x60: - case 0x70: - case 0x90: - case 0xA0: - m->command = CMD_S3MCMDEX; - // surround remap (this is the "official" command) - if(nNewType & MOD_TYPE_S3M && m->param == 0x91) - { - m->command = CMD_PANNING8; - m->param = 0xA4; - } - break; - } - break; - case CMD_KEYOFF: - if(m->note == 0) - { - m->note = (newTypeIsS3M) ? NOTE_NOTECUT : NOTE_KEYOFF; - m->command = CMD_S3MCMDEX; - if(m->param == 0) - m->instr = 0; - m->param = 0xD0 | (m->param & 0x0F); - } - break; - case CMD_PANNINGSLIDE: - // swap L/R - m->param = ((m->param & 0x0F) << 4) | (m->param >> 4); - default: - break; - } - } // End if(oldTypeIsMOD_XM && newTypeIsS3M_IT_MPT) - - - ///////////////////////////////////////// - // Convert S3M / IT / MPTM to MOD / XM - else if(oldTypeIsS3M_IT_MPT && newTypeIsMOD_XM) - { - if(m->note == NOTE_NOTECUT) - { - // convert note cut to EC0 - m->note = NOTE_NONE; - m->command = CMD_MODCMDEX; - m->param = 0xC0; - } else if(m->note == NOTE_FADE) - { - // convert note fade to note off - m->note = NOTE_KEYOFF; - } - - switch(m->command) - { - case CMD_S3MCMDEX: - S3MSxx2MODExx(m); - break; - case CMD_VOLUMESLIDE: - if ((m->param & 0xF0) && ((m->param & 0x0F) == 0x0F)) - { - m->command = CMD_MODCMDEX; - m->param = (m->param >> 4) | 0xA0; - } else - if ((m->param & 0x0F) && ((m->param & 0xF0) == 0xF0)) - { - m->command = CMD_MODCMDEX; - m->param = (m->param & 0x0F) | 0xB0; - } - break; - case CMD_PORTAMENTOUP: - if (m->param >= 0xF0) - { - m->command = CMD_MODCMDEX; - m->param = (m->param & 0x0F) | 0x10; - } else - if (m->param >= 0xE0) - { - m->command = CMD_MODCMDEX; - m->param = (((m->param & 0x0F)+3) >> 2) | 0x10; - } else m->command = CMD_PORTAMENTOUP; - break; - case CMD_PORTAMENTODOWN: - if (m->param >= 0xF0) - { - m->command = CMD_MODCMDEX; - m->param = (m->param & 0x0F) | 0x20; - } else - if (m->param >= 0xE0) - { - m->command = CMD_MODCMDEX; - m->param = (((m->param & 0x0F)+3) >> 2) | 0x20; - } else m->command = CMD_PORTAMENTODOWN; - break; - case CMD_SPEED: - { - m->param = min(m->param, (nNewType == MOD_TYPE_XM) ? 0x1F : 0x20); - } - break; - case CMD_TEMPO: - if(m->param < 0x20) m->command = CMD_NONE; // no tempo slides - break; - case CMD_PANNINGSLIDE: - // swap L/R - m->param = ((m->param & 0x0F) << 4) | (m->param >> 4); - // remove fine slides - if((m->param > 0xF0) || ((m->param & 0x0F) == 0x0F && m->param != 0x0F)) - m->command = CMD_NONE; - default: - break; - } - } // End if(oldTypeIsS3M_IT_MPT && newTypeIsMOD_XM) - - - /////////////////////// - // Convert IT to S3M - else if(oldTypeIsIT_MPT && newTypeIsS3M) - { - if(m->note == NOTE_KEYOFF || m->note == NOTE_FADE) - m->note = NOTE_NOTECUT; - - switch(m->command) - { - case CMD_S3MCMDEX: - if(m->param == 0x91) - { - // surround remap (this is the "official" command) - m->command = CMD_PANNING8; - m->param = 0xA4; - } - break; - case CMD_SMOOTHMIDI: - m->command = CMD_MIDI; - break; - default: - break; - } - } // End if (oldTypeIsIT_MPT && newTypeIsS3M) - - /////////////////////////////////// - // MOD <-> XM: Speed/Tempo update - if(oldTypeIsMOD && newTypeIsXM) - { - switch(m->command) - { - case CMD_SPEED: - m->param = min(m->param, 0x1F); - break; - } - } else if(oldTypeIsXM && newTypeIsMOD) - { - switch(m->command) - { - case CMD_TEMPO: - m->param = max(m->param, 0x21); - break; - } - } - - - /////////////////////////////////////////////////////////////////////// - // Convert MOD to anything - adjust effect memory, remove Invert Loop - if (oldTypeIsMOD) - { - switch(m->command) - { - case CMD_TONEPORTAVOL: // lacks memory -> 500 is the same as 300 - if(m->param == 0x00) m->command = CMD_TONEPORTAMENTO; - break; - case CMD_VIBRATOVOL: // lacks memory -> 600 is the same as 400 - if(m->param == 0x00) m->command = CMD_VIBRATO; - break; - - case CMD_MODCMDEX: // This would turn into "Set Active Macro", so let's better remove it - case CMD_S3MCMDEX: - if((m->param & 0xF0) == 0xF0) m->command = CMD_NONE; - break; - } - } // End if (oldTypeIsMOD && newTypeIsXM) - - ///////////////////////////////////////////////////////////////////// - // Convert anything to MOD - remove volume column, remove Set Macro - if (newTypeIsMOD) - { - // convert note off events - if(m->note >= NOTE_MIN_SPECIAL) - { - m->note = NOTE_NONE; - // no effect present, so just convert note off to volume 0 - if(m->command == CMD_NONE) - { - m->command = CMD_VOLUME; - m->param = 0; - // EDx effect present, so convert it to ECx - } else if((m->command == CMD_MODCMDEX) && ((m->param & 0xF0) == 0xD0)) - { - m->param = 0xC0 | (m->param & 0x0F); - } - } - - 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; - } - - 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; - } - m->volcmd = CMD_NONE; - } // End if (newTypeIsMOD) - - /////////////////////////////////////////////////// - // Convert anything to S3M - adjust volume column - if (newTypeIsS3M) - { - 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; - } - } // End if (newTypeIsS3M) - - //////////////////////////////////////////////////////////////////////// - // Convert anything to XM - adjust volume column, breaking EDx command - if (newTypeIsXM) - { - // remove EDx if no note is next to it, or it will retrigger the note in FT2 mode - if(m->command == CMD_MODCMDEX && (m->param & 0xF0) == 0xD0 && m->note == NOTE_NONE) - { - m->command = m->param = 0; - } - - 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; - } - } // End if (newTypeIsXM) - - /////////////////////////////////////////////////// - // Convert anything to IT - adjust volume column - if (newTypeIsIT_MPT) - { - 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; - } - } // End if (newTypeIsIT) - - if(!CSoundFile::GetModSpecifications(nNewType).HasNote(m->note)) - m->note = NOTE_NONE; - - // ensure the commands really exist in this format - if(CSoundFile::GetModSpecifications(nNewType).HasCommand(m->command) == false) - m->command = CMD_NONE; - if(CSoundFile::GetModSpecifications(nNewType).HasVolCommand(m->volcmd) == false) - m->volcmd = CMD_NONE; - -} - - -// "importance" of every FX command. Table is used for importing from formats with multiple effect colums -// and is approximately the same as in SchismTracker. -uint16 CSoundFile::GetEffectWeight(MODCOMMAND::COMMAND cmd) -//--------------------------------------------------------- -{ - switch(cmd) - { - case CMD_PATTERNBREAK: return 288; - case CMD_POSITIONJUMP: return 280; - case CMD_SPEED: return 272; - case CMD_TEMPO: return 264; - case CMD_GLOBALVOLUME: return 256; - case CMD_GLOBALVOLSLIDE: return 248; - case CMD_CHANNELVOLUME: return 240; - case CMD_CHANNELVOLSLIDE: return 232; - case CMD_TONEPORTAVOL: return 224; - case CMD_TONEPORTAMENTO: return 216; - case CMD_ARPEGGIO: return 208; - case CMD_RETRIG: return 200; - case CMD_TREMOR: return 192; - case CMD_OFFSET: return 184; - case CMD_VOLUME: return 176; - case CMD_VIBRATOVOL: return 168; - case CMD_VOLUMESLIDE: return 160; - case CMD_PORTAMENTODOWN: return 152; - case CMD_PORTAMENTOUP: return 133; - case CMD_NOTESLIDEDOWN: return 136; - case CMD_NOTESLIDEUP: return 128; - case CMD_PANNING8: return 120; - case CMD_PANNINGSLIDE: return 112; - case CMD_SMOOTHMIDI: return 104; - case CMD_MIDI: return 96; - case CMD_DELAYCUT: return 88; - case CMD_MODCMDEX: return 80; - case CMD_S3MCMDEX: return 72; - case CMD_PANBRELLO: return 64; - case CMD_XFINEPORTAUPDOWN: return 56; - case CMD_VIBRATO: return 48; - case CMD_FINEVIBRATO: return 40; - case CMD_TREMOLO: return 32; - case CMD_KEYOFF: return 24; - case CMD_SETENVPOSITION: return 16; - case CMD_XPARAM: return 8; - case CMD_NONE: - default: return 0; - } -} - -// 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; -} Added: trunk/OpenMPT/soundlib/modcommand.cpp =================================================================== --- trunk/OpenMPT/soundlib/modcommand.cpp (rev 0) +++ trunk/OpenMPT/soundlib/modcommand.cpp 2010-07-13 14:01:29 UTC (rev 643) @@ -0,0 +1,911 @@ +/* + * modcommand.cpp + * -------------- + * Purpose: Various functions for writing effects to patterns, converting MODCOMMANDs, etc. + * Authors: OpenMPT Devs + * + */ + +#include "stdafx.h" +#include "Sndfile.h" + +extern BYTE ImpulseTrackerPortaVolCmd[16]; + + +// Convert an Exx command (MOD) to Sxx command (S3M) +void CSoundFile::MODExx2S3MSxx(MODCOMMAND *m) +//------------------------------------------- +{ + if(m->command != CMD_MODCMDEX) return; + m->command = CMD_S3MCMDEX; + switch(m->param & 0xF0) + { + case 0x10: m->command = CMD_PORTAMENTOUP; m->param |= 0xF0; break; + case 0x20: m->command = CMD_PORTAMENTODOWN; m->param |= 0xF0; break; + case 0x30: m->param = (m->param & 0x0F) | 0x10; break; + case 0x40: m->param = (m->param & 0x03) | 0x30; break; + case 0x50: m->param = (m->param & 0x0F) | 0x20; break; + case 0x60: m->param = (m->param & 0x0F) | 0xB0; break; + case 0x70: m->param = (m->param & 0x03) | 0x40; break; + case 0x90: m->command = CMD_RETRIG; m->param = 0x80 | (m->param & 0x0F); break; + case 0xA0: if (m->param & 0x0F) { m->command = CMD_VOLUMESLIDE; m->param = (m->param << 4) | 0x0F; } else m->command = 0; break; + case 0xB0: if (m->param & 0x0F) { m->command = CMD_VOLUMESLIDE; m->param |= 0xF0; } else m->command = 0; break; + case 0xC0: if (m->param == 0xC0) { m->command = CMD_NONE; m->note = NOTE_NOTECUT; } // this does different things in IT and ST3 + case 0xD0: if (m->param == 0xD0) { m->command = CMD_NONE; } // dito + // rest are the same + } +} + + +// Convert an Sxx command (S3M) to Exx command (MOD) +void CSoundFile::S3MSxx2MODExx(MODCOMMAND *m) +//------------------------------------------- +{ + if(m->command != CMD_S3MCMDEX) return; + m->command = CMD_MODCMDEX; + switch(m->param & 0xF0) + { + case 0x10: m->param = (m->param & 0x0F) | 0x30; break; + case 0x20: m->param = (m->param & 0x0F) | 0x50; break; + case 0x30: m->param = (m->param & 0x0F) | 0x40; break; + case 0x40: m->param = (m->param & 0x0F) | 0x70; break; + case 0x50: + case 0x60: + case 0x70: if(((m->param & 0xF0) == 0x70) && ((m->param & 0x0F) > 0x0A)) { m->command = CMD_NONE; break; } // no pitch env in XM format + case 0x90: + case 0xA0: m->command = CMD_XFINEPORTAUPDOWN; break; + case 0xB0: m->param = (m->param & 0x0F) | 0x60; break; + // rest are the same + } +} + + +// Convert a mod command from one format to another. +void CSoundFile::ConvertCommand(MODCOMMAND *m, MODTYPE nOldType, MODTYPE nNewType) +//-------------------------------------------------------------------------------- +{ + // helper variables + const bool oldTypeIsMOD = (nOldType == MOD_TYPE_MOD), oldTypeIsXM = (nOldType == MOD_TYPE_XM), + oldTypeIsS3M = (nOldType == MOD_TYPE_S3M), oldTypeIsIT = (nOldType == MOD_TYPE_IT), + oldTypeIsMPT = (nOldType == MOD_TYPE_MPT), oldTypeIsMOD_XM = (oldTypeIsMOD || oldTypeIsXM), + oldTypeIsS3M_IT_MPT = (oldTypeIsS3M || oldTypeIsIT || oldTypeIsMPT), + oldTypeIsIT_MPT = (oldTypeIsIT || oldTypeIsMPT); + + const bool newTypeIsMOD = (nNewType == MOD_TYPE_MOD), newTypeIsXM = (nNewType == MOD_TYPE_XM), + newTypeIsS3M = (nNewType == MOD_TYPE_S3M), newTypeIsIT = (nNewType == MOD_TYPE_IT), + newTypeIsMPT = (nNewType == MOD_TYPE_MPT), newTypeIsMOD_XM = (newTypeIsMOD || newTypeIsXM), + newTypeIsS3M_IT_MPT = (newTypeIsS3M || newTypeIsIT || newTypeIsMPT), + newTypeIsIT_MPT = (newTypeIsIT || newTypeIsMPT); + + ////////////////////////// + // Convert 8-bit Panning + if(m->command == CMD_PANNING8) + { + if(newTypeIsS3M) + { + m->param = (m->param + 1) >> 1; + } + else if(oldTypeIsS3M) + { + if(m->param == 0xA4) + { + // surround remap + m->command = (nNewType & (MOD_TYPE_IT|MOD_TYPE_MPT)) ? CMD_S3MCMDEX : CMD_XFINEPORTAUPDOWN; + m->param = 0x91; + } + else + { + m->param = min(m->param << 1, 0xFF); + } + } + } // End if(m->command == CMD_PANNING8) + + /////////////////////////////////////////////////////////////////////////////////////// + // MPTM to anything: Convert param control, extended envelope control, note delay+cut + if(oldTypeIsMPT) + { + if(m->IsPcNote()) + { + m->param = (BYTE)(min(MODCOMMAND::maxColumnValue, m->GetValueEffectCol()) * 0x7F / MODCOMMAND::maxColumnValue); + m->command = (m->note == NOTE_PC) ? CMD_MIDI : CMD_SMOOTHMIDI; // might be removed later + m->volcmd = VOLCMD_NONE; + m->note = NOTE_NONE; + m->instr = 0; + } + + // adjust extended envelope control commands + if((m->command == CMD_S3MCMDEX) && ((m->param & 0xF0) == 0x70) && ((m->param & 0x0F) > 0x0C)) + { + m->param = 0x7C; + } + + if(m->command == CMD_DELAYCUT) + { + m->command = CMD_S3MCMDEX; // when converting to MOD/XM, this will be converted to CMD_MODCMDEX later + m->param = 0xD0 | (m->param >> 4); // preserve delay nibble. + } + } // End if(oldTypeIsMPT) + + ///////////////////////////////////////// + // Convert MOD / XM to S3M / IT / MPTM + if(oldTypeIsMOD_XM && newTypeIsS3M_IT_MPT) + { + switch(m->command) + { + case CMD_MODCMDEX: + MODExx2S3MSxx(m); + break; + case CMD_VOLUME: + if (!m->volcmd) + { + m->volcmd = VOLCMD_VOLUME; + m->vol = m->param; + if (m->vol > 0x40) m->vol = 0x40; + m->command = m->param = 0; + } + break; + case CMD_PORTAMENTOUP: + if (m->param > 0xDF) m->param = 0xDF; + break; + case CMD_PORTAMENTODOWN: + if (m->param > 0xDF) m->param = 0xDF; + break; + case CMD_XFINEPORTAUPDOWN: + switch(m->param & 0xF0) + { + case 0x10: m->command = CMD_PORTAMENTOUP; m->param = (m->param & 0x0F) | 0xE0; break; + case 0x20: m->command = CMD_PORTAMENTODOWN; m->param = (m->param & 0x0F) | 0xE0; break; + case 0x50: + case 0x60: + case 0x70: + case 0x90: + case 0xA0: + m->command = CMD_S3MCMDEX; + // surround remap (this is the "official" command) + if(nNewType & MOD_TYPE_S3M && m->param == 0x91) + { + m->command = CMD_PANNING8; + m->param = 0xA4; + } + break; + } + break; + case CMD_KEYOFF: + if(m->note == 0) + { + m->note = (newTypeIsS3M) ? NOTE_NOTECUT : NOTE_KEYOFF; + m->command = CMD_S3MCMDEX; + if(m->param == 0) + m->instr = 0; + m->param = 0xD0 | (m->param & 0x0F); + } + break; + case CMD_PANNINGSLIDE: + // swap L/R + m->param = ((m->param & 0x0F) << 4) | (m->param >> 4); + default: + break; + } + } // End if(oldTypeIsMOD_XM && newTypeIsS3M_IT_MPT) + + + ///////////////////////////////////////// + // Convert S3M / IT / MPTM to MOD / XM + else if(oldTypeIsS3M_IT_MPT && newTypeIsMOD_XM) + { + if(m->note == NOTE_NOTECUT) + { + // convert note cut to EC0 + m->note = NOTE_NONE; + m->command = CMD_MODCMDEX; + m->param = 0xC0; + } else if(m->note == NOTE_FADE) + { + // convert note fade to note off + m->note = NOTE_KEYOFF; + } + + switch(m->command) + { + case CMD_S3MCMDEX: + S3MSxx2MODExx(m); + break; + case CMD_VOLUMESLIDE: + if ((m->param & 0xF0) && ((m->param & 0x0F) == 0x0F)) + { + m->command = CMD_MODCMDEX; + m->param = (m->param >> 4) | 0xA0; + } else + if ((m->param & 0x0F) && ((m->param & 0xF0) == 0xF0)) + { + m->command = CMD_MODCMDEX; + m->param = (m->param & 0x0F) | 0xB0; + } + break; + case CMD_PORTAMENTOUP: + if (m->param >= 0xF0) + { + m->command = CMD_MODCMDEX; + m->param = (m->param & 0x0F) | 0x10; + } else + if (m->param >= 0xE0) + { + m->command = CMD_MODCMDEX; + m->param = (((m->param & 0x0F)+3) >> 2) | 0x10; + } else m->command = CMD_PORTAMENTOUP; + break; + case CMD_PORTAMENTODOWN: + if (m->param >= 0xF0) + { + m->command = CMD_MODCMDEX; + m->param = (m->param & 0x0F) | 0x20; + } else + if (m->param >= 0xE0) + { + m->command = CMD_MODCMDEX; + m->param = (((m->param & 0x0F)+3) >> 2) | 0x20; + } else m->command = CMD_PORTAMENTODOWN; + break; + case CMD_SPEED: + { + m->param = min(m->param, (nNewType == MOD_TYPE_XM) ? 0x1F : 0x20); + } + break; + case CMD_TEMPO: + if(m->param < 0x20) m->command = CMD_NONE; // no tempo slides + break; + case CMD_PANNINGSLIDE: + // swap L/R + m->param = ((m->param & 0x0F) << 4) | (m->param >> 4); + // remove fine slides + if((m->param > 0xF0) || ((m->param & 0x0F) == 0x0F && m->param != 0x0F)) + m->command = CMD_NONE; + default: + break; + } + } // End if(oldTypeIsS3M_IT_MPT && newTypeIsMOD_XM) + + + /////////////////////// + // Convert IT to S3M + else if(oldTypeIsIT_MPT && newTypeIsS3M) + { + if(m->note == NOTE_KEYOFF || m->note == NOTE_FADE) + m->note = NOTE_NOTECUT; + + switch(m->command) + { + case CMD_S3MCMDEX: + if(m->param == 0x91) + { + // surround remap (this is the "official" command) + m->command = CMD_PANNING8; + m->param = 0xA4; + } + break; + case CMD_SMOOTHMIDI: + m->command = CMD_MIDI; + break; + default: + break; + } + } // End if (oldTypeIsIT_MPT && newTypeIsS3M) + + /////////////////////////////////// + // MOD <-> XM: Speed/Tempo update + if(oldTypeIsMOD && newTypeIsXM) + { + switch(m->command) + { + case CMD_SPEED: + m->param = min(m->param, 0x1F); + break; + } + } else if(oldTypeIsXM && newTypeIsMOD) + { + switch(m->command) + { + case CMD_TEMPO: + m->param = max(m->param, 0x21); + break; + } + } + + + /////////////////////////////////////////////////////////////////////// + // Convert MOD to anything - adjust effect memory, remove Invert Loop + if (oldTypeIsMOD) + { + switch(m->command) + { + case CMD_TONEPORTAVOL: // lacks memory -> 500 is the same as 300 + if(m->param == 0x00) m->command = CMD_TONEPORTAMENTO; + break; + case CMD_VIBRATOVOL: // lacks memory -> 600 is the same as 400 + if(m->param == 0x00) m->command = CMD_VIBRATO; + break; + + case CMD_MODCMDEX: // This would turn into "Set Active Macro", so let's better remove it + case CMD_S3MCMDEX: + if((m->param & 0xF0) == 0xF0) m->command = CMD_NONE; + break; + } + } // End if (oldTypeIsMOD && newTypeIsXM) + + ///////////////////////////////////////////////////////////////////// + // Convert anything to MOD - remove volume column, remove Set Macro + if (newTypeIsMOD) + { + // convert note off events + if(m->note >= NOTE_MIN_SPECIAL) + { + m->note = NOTE_NONE; + // no effect present, so just convert note off to volume 0 + if(m->command == CMD_NONE) + { + m->command = CMD_VOLUME; + m->param = 0; + // EDx effect present, so convert it to ECx + } else if((m->command == CMD_MODCMDEX) && ((m->param & 0xF0) == 0xD0)) + { + m->param = 0xC0 | (m->param & 0x0F); + } + } + + 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; + } + + 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; + } + m->volcmd = CMD_NONE; + } // End if (newTypeIsMOD) + + /////////////////////////////////////////////////// + // Convert anything to S3M - adjust volume column + if (newTypeIsS3M) + { + 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; + } + } // End if (newTypeIsS3M) + + //////////////////////////////////////////////////////////////////////// + // Convert anything to XM - adjust volume column, breaking EDx command + if (newTypeIsXM) + { + // remove EDx if no note is next to it, or it will retrigger the note in FT2 mode + if(m->command == CMD_MODCMDEX && (m->param & 0xF0) == 0xD0 && m->note == NOTE_NONE) + { + m->command = m->param = 0; + } + + 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; + } + } // End if (newTypeIsXM) + + /////////////////////////////////////////////////// + // Convert anything to IT - adjust volume column + if (newTypeIsIT_MPT) + { + 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; + } + } // End if (newTypeIsIT) + + if(!CSoundFile::GetModSpecifications(nNewType).HasNote(m->note)) + m->note = NOTE_NONE; + + // ensure the commands really exist in this format + if(CSoundFile::GetModSpecifications(nNewType).HasCommand(m->command) == false) + m->command = CMD_NONE; + if(CSoundFile::GetModSpecifications(nNewType).HasVolCommand(m->volcmd) == false) + m->volcmd = CMD_NONE; + +} + + +// "importance" of every FX command. Table is used for importing from formats with multiple effect colums +// and is approximately the same as in SchismTracker. +uint16 CSoundFile::GetEffectWeight(MODCOMMAND::COMMAND cmd) +//--------------------------------------------------------- +{ + switch(cmd) + { + case CMD_PATTERNBREAK: return 288; + case CMD_POSITIONJUMP: return 280; + case CMD_SPEED: return 272; + case CMD_TEMPO: return 264; + case CMD_GLOBALVOLUME: return 256; + case CMD_GLOBALVOLSLIDE: return 248; + case CMD_CHANNELVOLUME: return 240; + case CMD_CHANNELVOLSLIDE: return 232; + case CMD_TONEPORTAVOL: return 224; + case CMD_TONEPORTAMENTO: return 216; + case CMD_ARPEGGIO: return 208; + case CMD_RETRIG: return 200; + case CMD_TREMOR: return 192; + case CMD_OFFSET: return 184; + case CMD_VOLUME: return 176; + case CMD_VIBRATOVOL: return 168; + case CMD_VOLUMESLIDE: return 160; + case CMD_PORTAMENTODOWN: return 152; + case CMD_PORTAMENTOUP: return 133; + case CMD_NOTESLIDEDOWN: return 136; + case CMD_NOTESLIDEUP: return 128; + case CMD_PANNING8: return 120; + case CMD_PANNINGSLIDE: return 112; + case CMD_SMOOTHMIDI: return 104; + case CMD_MIDI: return 96; + case CMD_DELAYCUT: return 88; + case CMD_MODCMDEX: return 80; + case CMD_S3MCMDEX: return 72; + case CMD_PANBRELLO: return 64; + case CMD_XFINEPORTAUPDOWN: return 56; + case CMD_VIBRATO: return 48; + case CMD_FINEVIBRATO: return 40; + case CMD_TREMOLO: return 32; + case CMD_KEYOFF: return 24; + case CMD_SETENVPOSITION: return 16; + case CMD_XPARAM: return 8; + case CMD_NONE: + default: return 0; + } +} + + +/* 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 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). 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) +*/ +bool CSoundFile::TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn, bool bAllowMultipleEffects, bool bAllowNextRow, bool bRetry) +//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +{ + // NOTE: Effect remapping is only implemented for a few basic effects. + CHANNELINDEX nScanChnMin = nChn, nScanChnMax = nChn; + MODCOMMAND *p = Patterns[nPat], *m; + + // Scan all channels + if(nChn == CHANNELINDEX_INVALID) + { + nScanChnMin = 0; + nScanChnMax = m_nChannels - 1; + } + + // Scan channel(s) for same effect type - if an effect of the same type is already present, exit. + if(!bAllowMultipleEffects) + { + for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++) + { + m = p + nRow * m_nChannels + i; + if(!bIsVolumeEffect && m->command == nEffect) + return true; + if(bIsVolumeEffect && m->volcmd == nEffect) + return true; + } + } + + // Easy case: check if there's some space left to put the effect somewhere + for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++) + { + m = p + nRow * m_nChannels + i; + if(!bIsVolumeEffect && m->command == CMD_NONE) + { + m->command = nEffect; + m->param = nParam; + return true; + } + if(bIsVolumeEffect && m->volcmd == VOLCMD_NONE) + { + m->volcmd = nEffect; + m->vol = nParam; + return true; + } + } + + // 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) + { + // Move some effects that also work in the volume column, so there's place for our new effect. + if(!bIsVolumeEffect) + { + for(CHANNELINDEX i = nScanChnMin; i <= nScanChnMax; i++) + { + m = p + nRow * m_nChannels + i; + switch(m->command) + { + case CMD_VOLUME: + m->volcmd = VOLCMD_VOLUME; + m->vol = m->param; + m->command = nEffect; + m->param = nParam; + return true; + + case CMD_PANNING8: + if(m_nType & MOD_TYPE_S3M && nParam > 0x80) + break; + + m->volcmd = VOLCMD_PANNING; + m->command = nEffect; + + if(m_nType & MOD_TYPE_S3M) + { + m->vol = m->param >> 1; + } + else + { + m->vol = (m->param >> 2) + 1; + } + + m->param = nParam; + return true; + } + } + } + + // Let's try it again by writing into the "other" effect column. + BYTE nNewEffect = CMD_NONE; + if(bIsVolumeEffect) + { + switch(nEffect) + { + case VOLCMD_PANNING: + nNewEffect = CMD_PANNING8; + if(m_nType & MOD_TYPE_S3M) + nParam <<= 1; + else + nParam = min(nParam << 2, 0xFF); + break; + case VOLCMD_VOLUME: + nNewEffect = CMD_VOLUME; + break; + } + } else + { + switch(nEffect) + { + case CMD_PANNING8: + nNewEffect = VOLCMD_PANNING; + if(m_nType & MOD_TYPE_S3M) + { + if(nParam <= 0x80) + nParam >>= 1; + else + nNewEffect = CMD_NONE; + } + else + { + nParam = (nParam >> 2) + 1; + } + break; + case CMD_VOLUME: + nNewEffect = CMD_VOLUME; + break; + } + } + if(nNewEffect != CMD_NONE) + { + if(TryWriteEffect(nPat, nRow, nNewEffect, nParam, !bIsVolumeEffect, nChn, bAllowMultipleEffects, bAllowNextRow, false) == true) return true; + } + } + + // Try in the next row if possible (this may also happen if we already retried) + if(bAllowNextRow && (nRow + 1 < Patterns[nPat].GetNumRows())) + { + return TryWriteEffect(nPat, nRow + 1, nEffect, nParam, bIsVolumeEffect, nChn, bAllowMultipleEffects, bAllowNextRow, bRetry); + } + + return false; +} + + +// 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; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-13 20:00:06
|
Revision: 645 http://modplug.svn.sourceforge.net/modplug/?rev=645&view=rev Author: saga-games Date: 2010-07-13 19:59:59 +0000 (Tue, 13 Jul 2010) Log Message: ----------- [Ref] Unified code for song message allocation / freeing / reading. From now on, Message.cpp ahould contain all code used for song messages. Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/Load_669.cpp trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/Load_far.cpp trunk/OpenMPT/soundlib/Load_gdm.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mdl.cpp trunk/OpenMPT/soundlib/Load_med.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/Load_mt2.cpp trunk/OpenMPT/soundlib/Load_mtm.cpp trunk/OpenMPT/soundlib/Load_ult.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Added Paths: ----------- trunk/OpenMPT/soundlib/Message.cpp Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2010-07-13 19:59:59 UTC (rev 645) @@ -346,6 +346,9 @@ RelativePath=".\MainFrm.cpp"> </File> <File + RelativePath="..\soundlib\Message.cpp"> + </File> + <File RelativePath=".\MIDIMappingDialog.cpp"> </File> <File @@ -394,6 +397,9 @@ RelativePath=".\mpt_midi.cpp"> </File> <File + RelativePath=".\MPTHacks.cpp"> + </File> + <File RelativePath=".\mptrack.cpp"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-07-13 19:59:59 UTC (rev 645) @@ -465,6 +465,10 @@ > </File> <File + RelativePath="..\soundlib\Message.cpp" + > + </File> + <File RelativePath=".\MIDIMappingDialog.cpp" > </File> @@ -529,6 +533,10 @@ > </File> <File + RelativePath=".\MPTHacks.cpp" + > + </File> + <File RelativePath=".\mptrack.cpp" > </File> Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2010-07-13 19:59:59 UTC (rev 645) @@ -119,21 +119,9 @@ psi = (DMFINFO *)(lpStream+dwMemPos); if (id == 0x47534d43) dwMemPos++; if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit; - if ((psi->infosize >= 8) && (!m_lpszSongComments)) + if (psi->infosize >= 8) { - m_lpszSongComments = new char[psi->infosize]; - if (m_lpszSongComments) - { - for (UINT i=0; i<psi->infosize-1; i++) - { - CHAR c = lpStream[dwMemPos+8+i]; - if ((i % 40) == 39) - m_lpszSongComments[i] = 0x0d; - else - m_lpszSongComments[i] = (c < ' ') ? ' ' : c; - } - m_lpszSongComments[psi->infosize-1] = 0; - } + ReadFixedLineLengthMessage(lpStream + dwMemPos + 8, psi->infosize - 1, 40, 0); } dwMemPos += psi->infosize + 8 - 1; break; Modified: trunk/OpenMPT/soundlib/Load_669.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_669.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_669.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -92,10 +92,10 @@ Samples[nSmp].nGlobalVol = 64; Samples[nSmp].nPan = 128; } + // Song Message - m_lpszSongComments = new char[109]; - memcpy(m_lpszSongComments, pfh->songmessage, 108); - m_lpszSongComments[108] = 0; + ReadFixedLineLengthMessage((BYTE *)(&pfh->songmessage), 108, 36, 0); + // Reading Orders Order.ReadAsByte(pfh->orders, 128, 128); m_nRestartPos = pfh->restartpos; @@ -106,6 +106,7 @@ ChnSettings[npan].nPan = (npan & 1) ? 0x30 : 0xD0; ChnSettings[npan].nVolume = 64; } + // Reading Patterns dwMemPos = 0x1F1 + pfh->samples * 25; for (UINT npat=0; npat<pfh->patterns; npat++) @@ -179,6 +180,7 @@ } dwMemPos += 0x600; } + // Reading Samples for (UINT n=1; n<=m_nSamples; n++) { Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -8,7 +8,7 @@ */ ////////////////////////////////////////////// -// AMS module loader // +// AMS (Extreme's Tracker) module loader // ////////////////////////////////////////////// #include "stdafx.h" #include "sndfile.h" @@ -53,7 +53,7 @@ DWORD dwMemPos; UINT tmp, tmp2; - if ((!lpStream) || (dwMemLength < 1024)) return false; + if ((!lpStream) || (dwMemLength < 126)) return false; if ((pfh->verhi != 0x01) || (strncmp(pfh->szHeader, "Extreme", 7)) || (!pfh->patterns) || (!pfh->orders) || (!pfh->samples) || (pfh->samples > MAX_SAMPLES) || (pfh->patterns > MAX_PATTERNS) || (pfh->orders > MAX_ORDERS)) @@ -61,12 +61,12 @@ return ReadAMS2(lpStream, dwMemLength); } dwMemPos = sizeof(AMSFILEHEADER) + pfh->extra; - if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) + 256 >= dwMemLength) return false; + if (dwMemPos + pfh->samples * sizeof(AMSSAMPLEHEADER) >= dwMemLength) return false; m_nType = MOD_TYPE_AMS; m_nInstruments = 0; m_nChannels = (pfh->chncfg & 0x1F) + 1; m_nSamples = pfh->samples; - for (UINT nSmp=1; nSmp<=m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) + for (UINT nSmp=1; nSmp <= m_nSamples; nSmp++, dwMemPos += sizeof(AMSSAMPLEHEADER)) { AMSSAMPLEHEADER *psh = (AMSSAMPLEHEADER *)(lpStream + dwMemPos); MODSAMPLE *pSmp = &Samples[nSmp]; @@ -83,14 +83,17 @@ if ((pSmp->nLoopEnd <= pSmp->nLength) && (pSmp->nLoopStart+4 <= pSmp->nLoopEnd)) pSmp->uFlags |= CHN_LOOP; pkinf[nSmp] = psh->infobyte; } + // Read Song Name + if (dwMemPos + 1 >= dwMemLength) return true; tmp = lpStream[dwMemPos++]; if (dwMemPos + tmp + 1 >= dwMemLength) return true; tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_szNames[0], lpStream+dwMemPos, tmp2); + if (tmp2) memcpy(m_szNames[0], lpStream + dwMemPos, tmp2); SpaceToNullStringFixed(m_szNames[0], tmp2); m_szNames[0][tmp2] = 0; dwMemPos += tmp; + // Read sample names for (UINT sNam=1; sNam<=m_nSamples; sNam++) { @@ -101,6 +104,7 @@ SpaceToNullStringFixed(m_szNames[sNam], tmp2); dwMemPos += tmp; } + // Read Channel names for (UINT cNam=0; cNam<m_nChannels; cNam++) { @@ -113,6 +117,7 @@ } dwMemPos += chnnamlen; } + // Read Pattern Names m_lpszPatternNames = new char[pfh->patterns * 32]; if (!m_lpszPatternNames) return true; @@ -126,24 +131,44 @@ if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2); dwMemPos += tmp; } + // Read Song Comments tmp = *((WORD *)(lpStream+dwMemPos)); dwMemPos += 2; if (dwMemPos + tmp >= dwMemLength) return true; - if (tmp) + if (tmp && AllocateMessage(tmp)) { - m_lpszSongComments = new char[tmp+1]; - if (!m_lpszSongComments) return true; - memset(m_lpszSongComments, 0, tmp+1); - memcpy(m_lpszSongComments, lpStream + dwMemPos, tmp); - dwMemPos += tmp; + // Translate that weird text format... + for(size_t i = 0; i < tmp; i++) + { + switch(lpStream[dwMemPos + i]) + { + case 0x00: + case 0x81: m_lpszSongComments[i] = ' '; break; + case 0x14: m_lpszSongComments[i] = '\xF6'; break; + case 0x19: m_lpszSongComments[i] = '\xD6'; break; + case 0x04: m_lpszSongComments[i] = '\xE4'; break; + case 0x0E: m_lpszSongComments[i] = '\xC4'; break; + case 0x06: m_lpszSongComments[i] = '\xE5'; break; + case 0x0F: m_lpszSongComments[i] = '\xC5'; break; + default: + if(lpStream[dwMemPos + i] > 0x81) + m_lpszSongComments[i] = '\r'; + else + m_lpszSongComments[i] = lpStream[dwMemPos + i]; + break; + } + } } + dwMemPos += tmp; + // Read Order List Order.resize(pfh->orders, Order.GetInvalidPatIndex()); for (UINT iOrd=0; iOrd < pfh->orders; iOrd++, dwMemPos += 2) { Order[iOrd] = (PATTERNINDEX)*((WORD *)(lpStream + dwMemPos)); } + // Read Patterns for (UINT iPat=0; iPat<pfh->patterns; iPat++) { @@ -244,6 +269,7 @@ } dwMemPos += len; } + // Read Samples for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) if (Samples[iSmp].nLength) { @@ -256,7 +282,7 @@ ///////////////////////////////////////////////////////////////////// -// AMS 2.2 loader +// AMS (Velvet Studio) 2.2 loader #pragma pack(1) @@ -441,12 +467,7 @@ UINT composernamelen = lpStream[dwMemPos]; if (composernamelen) { - m_lpszSongComments = new char[composernamelen+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, composernamelen); - m_lpszSongComments[composernamelen] = 0; - } + ReadMessage(lpStream + dwMemPos + 1, composernamelen, leCR); } dwMemPos += composernamelen + 1; // channel names Modified: trunk/OpenMPT/soundlib/Load_far.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_far.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_far.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -102,11 +102,7 @@ { UINT szLen = pmh1->stlen; if (szLen > dwMemLength - dwMemPos) szLen = dwMemLength - dwMemPos; - if ((m_lpszSongComments = new char[szLen + 1]) != NULL) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, szLen); - m_lpszSongComments[szLen] = 0; - } + ReadFixedLineLengthMessage(lpStream + dwMemPos, szLen, 132, 0); // 132 characters per line... wow. :) dwMemPos += pmh1->stlen; } // Reading orders Modified: trunk/OpenMPT/soundlib/Load_gdm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -272,7 +272,7 @@ for(UINT iRow = 0; iRow < 64; iRow++) { - do // zero byte = next row + while(true) // zero byte = next row { if(iPatternPos + 1 > dwMemLength) break; @@ -307,7 +307,7 @@ m->command = CMD_NONE; m->volcmd = CMD_NONE; - do + while(true) { if(iPatternPos + 2 > dwMemLength) break; BYTE bEffect = lpStream[iPatternPos++]; @@ -493,25 +493,20 @@ } if(!(bEffect & 0x20)) break; // no other effect follows - } while(1); + } } - } while(1); + } } iPatternsOffset += iPatternLength; } // read song comments - if(iMTLength) + if(iMTLength > 0) { - m_lpszSongComments = new char[iMTLength + 1]; - if (m_lpszSongComments) - { - memset(m_lpszSongComments, 0, iMTLength + 1); - memcpy(m_lpszSongComments, lpStream + iMTOffset, iMTLength); - } + ReadMessage(lpStream + iMTOffset, iMTLength, leAutodetect); } return true; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -507,23 +507,14 @@ streamPos += sizeof(DWORD); if(id > uint16_max) return false; - // allocate comment string - if(m_lpszSongComments) delete[] m_lpszSongComments; - if (id < dwMemLength && id > 0) + // allocate and copy comment string + ASSERT_CAN_READ(id); + if(id > 0) { - m_lpszSongComments = new char[id]; + ReadMessage(lpStream + streamPos, id - 1, leCR); } - else - m_lpszSongComments = NULL; + streamPos += id; - // m_lpszSongComments - if (m_lpszSongComments && id) - { - ASSERT_CAN_READ(id); - memcpy(&m_lpszSongComments[0],lpStream+streamPos,id); - streamPos += id; - } - // Song global config ASSERT_CAN_READ(5*4); @@ -1032,21 +1023,10 @@ // Reading Song Message if ((pifh->special & 0x01) && (pifh->msglength) && (pifh->msglength <= dwMemLength) && (pifh->msgoffset < dwMemLength - pifh->msglength)) { - m_lpszSongComments = new char[pifh->msglength+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+pifh->msgoffset, pifh->msglength); - m_lpszSongComments[pifh->msglength] = 0; - // ChibiTracker uses \n instead of \r. - if(pifh->cwtv == 0x0214 && pifh->cmwt == 0x0214 && LittleEndian(pifh->reserved) == IT_CHBI) - { - for(size_t i = 0; i < pifh->msglength; i++) - { - if(m_lpszSongComments[i] == '\n') - m_lpszSongComments[i] = '\r'; - } - } - } + // Generally, IT files should use CR for line endings. However, ChibiTracker uses LF. One could do... + // if(pifh->cwtv == 0x0214 && pifh->cmwt == 0x0214 && LittleEndian(pifh->reserved) == IT_CHBI) --> Chibi detected. + // But we'll just use autodetection here: + ReadMessage(lpStream + pifh->msgoffset, pifh->msglength, leAutodetect); } // Reading orders UINT nordsize = pifh->ordnum; Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mdl.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -300,15 +300,9 @@ #ifdef MDL_LOG Log("song message: %d bytes\n", blocklen); #endif - if (blocklen) + if(blocklen) { - if (m_lpszSongComments) delete[] m_lpszSongComments; - m_lpszSongComments = new char[blocklen]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, blocklen); - m_lpszSongComments[blocklen-1] = 0; - } + ReadMessage(lpStream + dwMemPos, blocklen - 1, leCR); } break; // PA: Pattern Data Modified: trunk/OpenMPT/soundlib/Load_med.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_med.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -696,18 +696,13 @@ if (pmex->channelsplit[i8ch]) m_nChannels++; } } - // Song Comments + // Song Comments (null-terminated) 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) && (annolen <= dwMemLength) && (annotxt <= dwMemLength - annolen) ) { - m_lpszSongComments = new char[annolen+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+annotxt, annolen); - m_lpszSongComments[annolen] = 0; - } + ReadMessage(lpStream + annotxt, annolen - 1, leAutodetect); } // Song Name UINT songname = BigEndian(pmex->songname); Modified: trunk/OpenMPT/soundlib/Load_mid.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mid.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mid.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -732,12 +732,7 @@ } else if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F)) { - m_lpszSongComments = new char [len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, ptrk->ptracks, len); - m_lpszSongComments[len] = 0; - } + ReadMessage(ptrk->ptracks, len, leAutodetect); } break; // FF.02 [text]: Song Copyright @@ -745,12 +740,7 @@ if (!len) break; if ((!m_lpszSongComments) && (ptrk->ptracks[0]) && (ptrk->ptracks[0] < 0x7F) && (len > 7)) { - m_lpszSongComments = new char [len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, ptrk->ptracks, len); - m_lpszSongComments[len] = 0; - } + ReadMessage(ptrk->ptracks, len, leAutodetect); } break; // FF.03: Sequence Name Modified: trunk/OpenMPT/soundlib/Load_mt2.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mt2.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mt2.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -252,16 +252,11 @@ { // MSG case 0x0047534D: - if ((dwLen > 3) && (!m_lpszSongComments)) + if (dwLen > 3) { DWORD nTxtLen = dwLen; if (nTxtLen > 32000) nTxtLen = 32000; - m_lpszSongComments = new char[nTxtLen]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos+1, nTxtLen-1); - m_lpszSongComments[nTxtLen-1] = 0; - } + ReadMessage(lpStream + dwMemPos + 1, nTxtLen - 1, leCRLF); } break; // SUM -> author name (or "Unregistered") Modified: trunk/OpenMPT/soundlib/Load_mtm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -139,19 +139,7 @@ if ((pmh->commentsize) && (dwMemPos + pmh->commentsize < dwMemLength)) { UINT n = pmh->commentsize; - m_lpszSongComments = new char[n+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, n); - m_lpszSongComments[n] = 0; - for (UINT i=0; i<n; i++) - { - if (!m_lpszSongComments[i]) - { - m_lpszSongComments[i] = ((i + 1) % 40) ? 0x20 : 0x0D; - } - } - } + ReadFixedLineLengthMessage(lpStream + dwMemPos, n, 39, 1); } dwMemPos += pmh->commentsize; // Reading Samples Modified: trunk/OpenMPT/soundlib/Load_ult.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ult.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_ult.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -332,18 +332,7 @@ 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) - { - for(size_t nLine = 0; nLine < nNumLines; nLine++) - { - memcpy(m_lpszSongComments + nLine * 33, lpStream + dwMemPos + nLine * 32, 32); - m_lpszSongComments[nLine * 33 + 32] = 0x0D; - } - m_lpszSongComments[nNumLines * 33] = 0; - } + ReadFixedLineLengthMessage(lpStream + dwMemPos, nNumLines * 32, 32, 0); dwMemPos += nNumLines * 32; ASSERT_CAN_READ(1); Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -607,12 +607,7 @@ dwMemPos += 8; if ((dwMemPos + len <= dwMemLength) && (len < 16384)) { - m_lpszSongComments = new char[len+1]; - if (m_lpszSongComments) - { - memcpy(m_lpszSongComments, lpStream+dwMemPos, len); - m_lpszSongComments[len] = 0; - } + ReadMessage(lpStream + dwMemPos, len, leCR); dwMemPos += len; } bMadeWithModPlug = true; Added: trunk/OpenMPT/soundlib/Message.cpp =================================================================== --- trunk/OpenMPT/soundlib/Message.cpp (rev 0) +++ trunk/OpenMPT/soundlib/Message.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -0,0 +1,242 @@ +/* + * Message.cpp + * ----------- + * Purpose: Various functions concerning song messages (allocating, reading from file...) + * Notes : Those functions should offer a rather high level of abstraction compared to + * previous ways of reading the song messages. There are still many things to do, + * though. Future versions of ReadMessage() could f.e. offer charset conversion + * and the code is not yet ready for unicode. + * Some functions for preparing the message text to be written to a file would + * also be handy. + * Authors: OpenMPT Devs + * + */ + +#include "stdafx.h" +#include "Sndfile.h" + + +// Allocate memory for song message. +// [in] length: text length in characters, without possible trailing null terminator. +// [out] returns true on success. +bool CSoundFile::AllocateMessage(size_t length) +//--------------------------------------------- +{ + FreeMessage(); + m_lpszSongComments = new char[length + 1]; // + 1 for trailing null + if(m_lpszSongComments == nullptr) + { + return false; + } else + { + memset(m_lpszSongComments, 0, length + 1); + return true; + } +} + + +// Free previously allocated song message memory +void CSoundFile::FreeMessage() +//---------------------------- +{ + if(m_lpszSongComments) + { + delete[] m_lpszSongComments; + m_lpszSongComments = nullptr; + } +} + + +// Read song message from a mapped file. +// [in] data: pointer to the data in memory that is going to be read +// [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). +// [in] lineEnding: line ending formatting of the text in memory. +// [out] returns true on success. +bool CSoundFile::ReadMessage(const BYTE *data, const size_t length, enmLineEndings lineEnding) +//-------------------------------------------------------------------------------------------- +{ + // Simple line-ending detection algorithm. VERY simple. + if(lineEnding == leAutodetect) + { + size_t nCR = 0, nLF = 0, nCRLF = 0; + // find CRs, LFs and CRLFs + for(size_t i = 0; i < length; i++) + { + if(data[i] == '\r') nCR++; + else if(data[i] == '\n') nLF++; + + if(i && data[i - 1] == '\r' && data[i] == '\n') nCRLF++; + } + // evaluate findings + if(nCR == nLF && nCR == nCRLF) + lineEnding = leCRLF; + else if(nCR && !nLF) + lineEnding = leCR; + else if(!nCR && nLF) + lineEnding = leLF; + else + lineEnding = leMixed; + } + + size_t final_length = 0; + // calculate the final amount of characters to be allocated. + for(size_t i = 0; i < length; i++) + { + switch(data[i]) + { + case '\r': + if(lineEnding != leLF) final_length++; + break; + case '\n': + if(lineEnding != leCR && lineEnding != leCRLF) final_length++; + break; + default: + final_length++; + break; + } + } + + if(!AllocateMessage(final_length)) + return false; + + size_t cpos = 0; + for(size_t i = 0; i < length; i++, cpos++) + { + switch(data[i]) + { + case '\r': + if(lineEnding != leLF) + m_lpszSongComments[cpos] = '\r'; + else + m_lpszSongComments[cpos] = ' '; + if(lineEnding == leCRLF) i++; // skip the LF + break; + case '\n': + if(lineEnding != leCR && lineEnding != leCRLF) + m_lpszSongComments[cpos] = '\r'; + else + m_lpszSongComments[cpos] = ' '; + break; + case '\0': + m_lpszSongComments[cpos] = ' '; + break; + default: + m_lpszSongComments[cpos] = data[i]; + break; + } + } + + return true; +} + + +// Read comments with fixed line length from a mapped file. +// [in] data: pointer to the data in memory that is going to be read +// [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). +// [in] lineLength: The fixed length of a line. +// [in] lineEndingLength: The padding space between two fikxed lines. (there could for example be a null char after every line) +// [out] returns true on success. +bool CSoundFile::ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength) +//---------------------------------------------------------------------------------------------------------------------------------------- +{ + if(lineLength == 0) + return false; + + const size_t num_lines = (length / (lineLength + lineEndingLength)); + const size_t final_length = num_lines * (lineLength + 1); + if(!AllocateMessage(final_length)) + return false; + + for(size_t line = 0, fpos = 0, cpos = 0; line < num_lines; line++, fpos += (lineLength + lineEndingLength), cpos += (lineLength + 1)) + { + memcpy(m_lpszSongComments + cpos, data + fpos, min(lineLength, length - fpos)); + m_lpszSongComments[cpos + lineLength] = '\r'; + + // fix weird chars + for(size_t lpos = 0; lpos < lineLength; lpos++) + { + switch(m_lpszSongComments[cpos + lpos]) + { + case '\0': + case '\n': + case '\r': + m_lpszSongComments[cpos + lpos] = ' '; + break; + } + + } + } + return true; +} + + +// OLD and unused function. Do we still need it? +UINT CSoundFile::GetSongMessage(LPSTR s, UINT len, UINT linesize) +//--------------------------------------------------------------- +{ + LPCSTR p = m_lpszSongComments; + if (!p) return 0; + UINT i = 2, ln=0; + if ((len) && (s)) s[0] = '\x0D'; + if ((len > 1) && (s)) s[1] = '\x0A'; + while ((*p) && (i+2 < len)) + { + BYTE c = (BYTE)*p++; + if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) + { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } + else + if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } + } + if (s) s[i] = 0; + return i; +} + + +// OLD and unused function. Do we still need it? +UINT CSoundFile::GetRawSongMessage(LPSTR s, UINT len, UINT linesize) +//------------------------------------------------------------------ +{ + LPCSTR p = m_lpszSongComments; + if (!p) return 0; + UINT i = 0, ln=0; + while ((*p) && (i < len-1)) + { + BYTE c = (BYTE)*p++; + if ((c == 0x0D) || (c == 0x0A)) + { + if (ln) + { + while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } + ln = 0; + } + } else + if ((c == ' ') && (!ln)) + { + UINT k=0; + while ((p[k]) && (p[k] >= ' ')) k++; + if (k <= linesize) + { + if (s) s[i] = ' '; + i++; + ln++; + } + } else + { + if (s) s[i] = c; + i++; + ln++; + if (ln == linesize) ln = 0; + } + } + if (ln) + { + while ((ln < linesize) && (i < len)) + { + if (s) s[i] = ' '; + i++; + ln++; + } + } + if (s) s[i] = 0; + return i; +} Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-13 19:59:59 UTC (rev 645) @@ -859,8 +859,7 @@ delete[] m_lpszPatternNames; m_lpszPatternNames = NULL; - delete[] m_lpszSongComments; - m_lpszSongComments = NULL; + FreeMessage(); for (i=1; i<MAX_SAMPLES; i++) { @@ -955,76 +954,6 @@ } -UINT CSoundFile::GetSongComments(LPSTR s, UINT len, UINT linesize) -//---------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 2, ln=0; - if ((len) && (s)) s[0] = '\x0D'; - if ((len > 1) && (s)) s[1] = '\x0A'; - while ((*p) && (i+2 < len)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || ((c == ' ') && (ln >= linesize))) - { if (s) { s[i++] = '\x0D'; s[i++] = '\x0A'; } else i+= 2; ln=0; } - else - if (c >= 0x20) { if (s) s[i++] = c; else i++; ln++; } - } - if (s) s[i] = 0; - return i; -} - - -UINT CSoundFile::GetRawSongComments(LPSTR s, UINT len, UINT linesize) -//------------------------------------------------------------------- -{ - LPCSTR p = m_lpszSongComments; - if (!p) return 0; - UINT i = 0, ln=0; - while ((*p) && (i < len-1)) - { - BYTE c = (BYTE)*p++; - if ((c == 0x0D) || (c == 0x0A)) - { - if (ln) - { - while (ln < linesize) { if (s) s[i] = ' '; i++; ln++; } - ln = 0; - } - } else - if ((c == ' ') && (!ln)) - { - UINT k=0; - while ((p[k]) && (p[k] >= ' ')) k++; - if (k <= linesize) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } else - { - if (s) s[i] = c; - i++; - ln++; - if (ln == linesize) ln = 0; - } - } - if (ln) - { - while ((ln < linesize) && (i < len)) - { - if (s) s[i] = ' '; - i++; - ln++; - } - } - if (s) s[i] = 0; - return i; -} - - BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) //---------------------------------------------------------------------------- { Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-13 19:19:41 UTC (rev 644) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-13 19:59:59 UTC (rev 645) @@ -443,7 +443,17 @@ #include "PlaybackEventer.h" +// Line ending types (for reading song messages from module files) +enum enmLineEndings +{ + leCR, // Carriage Return (0x0D, \r) + leLF, // Line Feed (0x0A \n) + leCRLF, // Carriage Return, Line Feed (0x0D0A, \r\n) + leMixed, // It is not defined whether Carriage Return or Line Feed is the actual line ending. Both are accepted. + leAutodetect, // Detect suitable line ending +}; + class CSoundFile; @@ -627,8 +637,6 @@ UINT GetCurrentPos() const; UINT GetCurrentPattern() const { return m_nPattern; } ORDERINDEX GetCurrentOrder() const { return static_cast<ORDERINDEX>(m_nCurrentPattern); } - UINT GetSongComments(LPSTR s, UINT cbsize, UINT linesize=32); - UINT GetRawSongComments(LPSTR s, UINT cbsize, UINT linesize=32); UINT GetMaxPosition() const; CHANNELINDEX GetNumChannels() const { return m_nChannels; } @@ -851,8 +859,8 @@ void GlobalVolSlide(UINT param, UINT * nOldGlobalVolSlide); DWORD IsSongFinished(UINT nOrder, UINT nRow) const; BOOL IsValidBackwardJump(UINT nStartOrder, UINT nStartRow, UINT nJumpOrder, UINT nJumpRow) const; + public: - // Write pattern effect functions bool TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn = CHANNELINDEX_INVALID, bool bAllowMultipleEffects = true, bool bAllowNextRow = false, bool bRetry = true); @@ -937,12 +945,41 @@ static LPSTR AllocateSample(UINT nbytes); static void FreeSample(LPVOID p); static UINT Normalize24BitBuffer(LPBYTE pbuffer, UINT cbsizebytes, DWORD lmax24, DWORD dwByteInc); - UINT GetBestPlugin(UINT nChn, UINT priority, bool respectMutes); //private: static MODCOMMAND *AllocatePattern(UINT rows, UINT nchns); static void FreePattern(LPVOID pat); + // Song message helper functions public: + // Allocate memory for song message. + // [in] length: text length in characters, without possible trailing null terminator. + // [out] returns true on success. + bool AllocateMessage(size_t length); + + // Free previously allocated song message memory. + void FreeMessage(); + +protected: + // Read song message from a mapped file. + // [in] data: pointer to the data in memory that is going to be read + // [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). + // [in] lineEnding: line ending formatting of the text in memory. + // [out] returns true on success. + bool ReadMessage(const BYTE *data, const size_t length, enmLineEndings lineEnding); + + // Read comments with fixed line length from a mapped file. + // [in] data: pointer to the data in memory that is going to be read + // [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). + // [in] lineLength: The fixed length of a line. + // [in] lineEndingLength: The padding space between two fikxed lines. (there could for example be a null char after every line) + // [out] returns true on success. + bool ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength); + + // Currently unused (and the code doesn't look very nice :) + UINT GetSongMessage(LPSTR s, UINT cbsize, UINT linesize=32); + UINT GetRawSongMessage(LPSTR s, UINT cbsize, UINT linesize=32); + +public: int getVolEnvValueFromPosition(int position, MODINSTRUMENT* pIns); void resetEnvelopes(MODCHANNEL* pChn, enmResetEnv envToReset = ENV_RESET_ALL); void SetDefaultInstrumentValues(MODINSTRUMENT *pIns); @@ -955,6 +992,9 @@ void BuildDefaultInstrument(); long GetSampleOffset(); +public: + UINT GetBestPlugin(UINT nChn, UINT priority, bool respectMutes); + // 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); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-16 21:46:25
|
Revision: 650 http://modplug.svn.sourceforge.net/modplug/?rev=650&view=rev Author: saga-games Date: 2010-07-16 21:46:18 +0000 (Fri, 16 Jul 2010) Log Message: ----------- [Fix] PSM16 loader: Since the control channels were muted, tempo commands were ignored, effectively slowing down some PSM16 tracks. [Imp] Improved handling of automatic modtype conversion of non-native formats. Compatibility flag is now always preserved. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/soundlib/Load_imf.cpp trunk/OpenMPT/soundlib/Load_psm.cpp trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/Tables.cpp trunk/OpenMPT/soundlib/load_j2b.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-16 21:46:18 UTC (rev 650) @@ -364,7 +364,9 @@ case MOD_TYPE_AMF: m_SndFile.ChangeModTypeTo(MOD_TYPE_S3M); break; + case MOD_TYPE_IMF: case MOD_TYPE_PSM: + case MOD_TYPE_J2B: case MOD_TYPE_ULT: case MOD_TYPE_OKT: case MOD_TYPE_MT2: Modified: trunk/OpenMPT/soundlib/Load_imf.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_imf.cpp 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/Load_imf.cpp 2010-07-16 21:46:18 UTC (rev 650) @@ -288,7 +288,7 @@ if (memcmp(hdr.im10, "IM10", 4) != 0) return false; - ChangeModTypeTo(MOD_TYPE_IT); + m_nType = MOD_TYPE_IMF; SetModFlag(MSF_COMPATIBLE_PLAY, true); // song name Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2010-07-16 21:46:18 UTC (rev 650) @@ -136,7 +136,7 @@ ) return false; // Yep, this seems to be a valid file. - m_nType = MOD_TYPE_IT; + m_nType = MOD_TYPE_PSM; SetModFlag(MSF_COMPATIBLE_PLAY, true); m_nChannels = 0; @@ -920,7 +920,7 @@ { ChnSettings[i].nPan = lpStream[dwMemPos + i] << 4; ChnSettings[i].nVolume = 64; - ChnSettings[i].dwFlags = (i >= shdr->numChannelsPlay) ? CHN_MUTE : 0; + ChnSettings[i].dwFlags = 0; // (i >= shdr->numChannelsPlay) ? CHN_MUTE : 0; // don't mute channels, as muted channels are completely ignored in S3M } } Modified: trunk/OpenMPT/soundlib/Snd_defs.h =================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/Snd_defs.h 2010-07-16 21:46:18 UTC (rev 650) @@ -113,8 +113,8 @@ #define MOD_TYPE_PSM 0x400000 #define MOD_TYPE_J2B 0x800000 #define MOD_TYPE_MPT 0x1000000 +#define MOD_TYPE_IMF 0x2000000 #define MOD_TYPE_UMX 0x80000000 // Fake type -#define MAX_MODTYPE 24 // For compatibility mode #define TRK_IMPULSETRACKER MOD_TYPE_IT | MOD_TYPE_MPT Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2010-07-16 21:46:18 UTC (rev 650) @@ -3013,13 +3013,13 @@ // XM <-> IT/MPT conversion. if(combined == (MOD_TYPE_IT|MOD_TYPE_XM) || combined == (MOD_TYPE_MPT|MOD_TYPE_XM)) - return (1 << MSF_COMPATIBLE_PLAY) + (1 << MSF_MIDICC_BUGEMULATION); + return (1 << MSF_COMPATIBLE_PLAY) | (1 << MSF_MIDICC_BUGEMULATION); // IT <-> MPT conversion. if(combined == (MOD_TYPE_IT|MOD_TYPE_MPT)) return uint16_max; - return 0; + return (1 << MSF_COMPATIBLE_PLAY); } void CSoundFile::ChangeModTypeTo(const MODTYPE& newType) Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-16 21:46:18 UTC (rev 650) @@ -1199,7 +1199,7 @@ DWORD dwPadding; } MODFORMATINFO; -extern MODFORMATINFO gModFormatInfo[MAX_MODTYPE]; +extern MODFORMATINFO gModFormatInfo[]; #endif Modified: trunk/OpenMPT/soundlib/Tables.cpp =================================================================== --- trunk/OpenMPT/soundlib/Tables.cpp 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/Tables.cpp 2010-07-16 21:46:18 UTC (rev 650) @@ -25,7 +25,7 @@ /////////////////////////////////////////////////////////////////////// #ifndef FASTSOUNDLIB -MODFORMATINFO gModFormatInfo[MAX_MODTYPE] = +MODFORMATINFO gModFormatInfo[] = { { MOD_TYPE_MOD, "ProTracker", ".mod", 0 }, { MOD_TYPE_S3M, "ScreamTracker III", ".s3m", 0 }, @@ -42,15 +42,17 @@ { MOD_TYPE_PTM, "PolyTracker", ".ptm", 0 }, { MOD_TYPE_WAV, "Wave", ".wav", 0 }, { MOD_TYPE_MID, "Midi", ".mid", 0 }, - { MOD_TYPE_AMS, "Extreme Tracker", ".ams", 0 }, + { MOD_TYPE_AMS, "Extreme's Tracker", ".ams", 0 }, { MOD_TYPE_AMF|MOD_TYPE_AMF0,"Asylum / DSMI", ".amf", 0 }, { MOD_TYPE_DSM, "DSIK Format", ".dsm", 0 }, { MOD_TYPE_DMF, "X-Tracker", ".dmf", 0 }, { MOD_TYPE_DBM, "DigiBooster Pro", ".dbm", 0 }, - { MOD_TYPE_PSM, "Protracker Studio", ".psm", 0 }, + { MOD_TYPE_PSM, "Epic Megagames MASI", ".psm", 0 }, { MOD_TYPE_UMX, "Unreal Music", ".umx", 0 }, { MOD_TYPE_MT2, "MadTracker 2", ".mt2", 0 }, - { MOD_TYPE_MPT, "OpenMPT", ".mptm", 0 }, + { MOD_TYPE_MPT, "OpenMPT", ".mptm", 0 }, + { MOD_TYPE_J2B, "Galaxy Sound System", ".j2b", 0 }, + { MOD_TYPE_IMF, "Imago Orpheus", ".imf", 0 }, }; #endif Modified: trunk/OpenMPT/soundlib/load_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-07-16 21:43:14 UTC (rev 649) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-07-16 21:46:18 UTC (rev 650) @@ -502,7 +502,7 @@ m_nDefaultTempo = mainchunk->tempo; m_nDefaultGlobalVolume = mainchunk->globalvolume << 1; m_nSamplePreAmp = m_nVSTiVolume = 48; - m_nType = MOD_TYPE_IT; + m_nType = MOD_TYPE_J2B; ASSERT(LittleEndian(mainchunk->unknown) == 0xFF0001C5 || LittleEndian(mainchunk->unknown) == 0x35800716); // It seems like there's no way to differentiate between This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-17 18:28:58
|
Revision: 652 http://modplug.svn.sourceforge.net/modplug/?rev=652&view=rev Author: saga-games Date: 2010-07-17 18:28:51 +0000 (Sat, 17 Jul 2010) Log Message: ----------- [Imp] IT Saver: If filter envelopes are used, a different value for the cmwt field is now used in compatiblity export (like in SchismTracker). [Ref] Mod Savers: From now on, the CModDoc text log system should be used for displaying warnings during saving, so that unnecessary messageboxes are not shown anymore during autosave. [Mod] OpenMPT: Version is now 1.18.02.04 Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_mod.cpp Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-16 23:18:40 UTC (rev 651) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-07-17 18:28:51 UTC (rev 652) @@ -424,6 +424,7 @@ return bOk; } BeginWaitCursor(); + ClearLog(); switch(nType) { case MOD_TYPE_MOD: bOk = m_SndFile.SaveMod(lpszPathName, dwPacking); break; @@ -436,6 +437,7 @@ if (bOk) { if (nType == m_SndFile.m_nType) SetPathName(lpszPathName); + ShowLog(); } else { if(nType == MOD_TYPE_IT && m_SndFile.m_dwSongFlags & SONG_ITPROJECT) ::MessageBox(NULL,"ITP projects need to have a path set for each instrument...",NULL,MB_ICONERROR | MB_OK); @@ -1757,6 +1759,7 @@ FileDlgResult files = CTrackApp::ShowOpenSaveFileDialog(false, ext, filename, pattern, CMainFrame::GetWorkingDirectory(DIR_MODS)); if(files.abort) return; + ClearLog(); switch (type) { case MOD_TYPE_MOD: @@ -1771,6 +1774,7 @@ m_SndFile.SaveCompatIT(files.first_file.c_str()); break; } + ShowLog(); } Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-07-16 23:18:40 UTC (rev 651) +++ trunk/OpenMPT/mptrack/version.h 2010-07-17 18:28:51 UTC (rev 652) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 #define VER_MINOR 02 -#define VER_MINORMINOR 03 +#define VER_MINORMINOR 04 //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_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-16 23:18:40 UTC (rev 651) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-07-17 18:28:51 UTC (rev 652) @@ -2502,8 +2502,18 @@ header.smpnum = m_nSamples; MptVersion::VersionNum vVersion = MptVersion::num; - header.cwtv = 0x5000 | (WORD)((vVersion >> 16) & 0x0FFF); // format: txyy (t = tracker ID, x = version major, yy = version minor), e.g. 0x5117 (OpenMPT = 5, 117 = v1.17) - header.cmwt = 0x0214; // Common compatible tracker :) + header.cwtv = LittleEndianW(0x5000 | (WORD)((vVersion >> 16) & 0x0FFF)); // format: txyy (t = tracker ID, x = version major, yy = version minor), e.g. 0x5117 (OpenMPT = 5, 117 = v1.17) + header.cmwt = LittleEndianW(0x0214); // Common compatible tracker :) + // hack from schism tracker: + for(INSTRUMENTINDEX nIns = 1; nIns <= GetNumInstruments(); nIns++) + { + if(Instruments[nIns] && Instruments[nIns]->PitchEnv.dwFlags & ENV_FILTER) + { + header.cmwt = LittleEndianW(0x0217); + break; + } + } + header.flags = 0x0001; header.special = 0x0006; if (m_nInstruments) header.flags |= 0x04; Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2010-07-16 23:18:40 UTC (rev 651) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2010-07-17 18:28:51 UTC (rev 652) @@ -453,12 +453,16 @@ return true; #else return bSamplesPresent; -#endif +#endif // MODPLUG_TRACKER } #ifndef MODPLUG_NO_FILESAVE +#ifdef MODPLUG_TRACKER +#include "../mptrack/moddoc.h" +#endif // MODPLUG_TRACKER + bool CSoundFile::SaveMod(LPCSTR lpszFileName, UINT nPacking, const bool bCompatibilityExport) //------------------------------------------------------------------------------------------- { @@ -588,14 +592,19 @@ } //end for all patterns //Check for unsaved patterns - for (UINT ipat=nbp; ipat<MAX_PATTERNS; ipat++) +#ifdef MODPLUG_TRACKER + if(GetpModDoc() != nullptr) { - if (Patterns[ipat]) + for(UINT ipat = nbp; ipat < MAX_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; + if(Patterns[ipat]) + { + GetpModDoc()->AddToLog(_T("Warning: This track contains at least one pattern after the highest pattern number referred to in the sequence. Such patterns are not saved in the .mod format.\n")); + break; + } } } +#endif // Writing instruments for (UINT ismpd = 1; ismpd <= 31; ismpd++) if (inslen[ismpd]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-17 22:19:13
|
Revision: 654 http://modplug.svn.sourceforge.net/modplug/?rev=654&view=rev Author: saga-games Date: 2010-07-17 22:19:07 +0000 (Sat, 17 Jul 2010) Log Message: ----------- [Reg] Envelope release nodes cannot be enabled for IT files anymore, but they are still played for compatibility. (One has to start removing the crap from the old formats at some point...) [Imp] Mod Conversion: Envelope release nodes are now removed when converting from MPTM. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_ins.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/mod_specifications.h Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2010-07-17 20:34:45 UTC (rev 653) +++ trunk/OpenMPT/mptrack/Moddoc.h 2010-07-17 22:19:07 UTC (rev 654) @@ -51,7 +51,7 @@ STATIC_ASSERT( (HINT_MASK_ITEM & HINT_MASK_FLAGS) == 0 ); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// NOTE : be carefull when adding new flags !!! +// NOTE : be careful when adding new flags !!! // ------------------------------------------------------------------------------------------------------------------------- // those flags are passed through a 32bits parameter which can also contain instrument/sample/pattern row... number : // HINT_SAMPLEINFO & HINT_SAMPLEDATA & HINT_SMPNAMES : can be used with a sample number 12bit coded (passed as bit 20 to 31) @@ -172,7 +172,7 @@ void SetShowSaveDialog(bool b) {m_ShowSavedialog = b;} void PostMessageToAllViews(UINT uMsg, WPARAM wParam=0, LPARAM lParam=0); void SendMessageToActiveViews(UINT uMsg, WPARAM wParam=0, LPARAM lParam=0); - UINT GetModType() const { return m_SndFile.m_nType; } + MODTYPE GetModType() const { return m_SndFile.m_nType; } INSTRUMENTINDEX GetNumInstruments() const { return m_SndFile.m_nInstruments; } SAMPLEINDEX GetNumSamples() const { return m_SndFile.m_nSamples; } BOOL AddToLog(LPCSTR lpszLog); @@ -334,7 +334,7 @@ //}}AFX_VIRTUAL // for mod conversion - bool UpdateEnvelopes(INSTRUMENTENVELOPE *mptEnv); + uint8 UpdateEnvelopes(INSTRUMENTENVELOPE *mptEnv); // Implementation Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-17 20:34:45 UTC (rev 653) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-17 22:19:07 UTC (rev 654) @@ -379,15 +379,17 @@ m_SndFile.m_nDefaultTempo = CLAMP(m_SndFile.m_nDefaultTempo, specs.tempoMin, specs.tempoMax); m_SndFile.m_nDefaultSpeed = CLAMP(m_SndFile.m_nDefaultSpeed, specs.speedMin, specs.speedMax); - bool bTrimmedEnvelopes = false; + uint8 trimmedEnvelopes = 0; for(INSTRUMENTINDEX i = 1; i <= m_SndFile.m_nInstruments; i++) if(m_SndFile.Instruments[i] != nullptr) { - bTrimmedEnvelopes |= UpdateEnvelopes(&(m_SndFile.Instruments[i]->VolEnv)); - bTrimmedEnvelopes |= UpdateEnvelopes(&(m_SndFile.Instruments[i]->PanEnv)); - bTrimmedEnvelopes |= UpdateEnvelopes(&(m_SndFile.Instruments[i]->PitchEnv)); + trimmedEnvelopes |= UpdateEnvelopes(&(m_SndFile.Instruments[i]->VolEnv)); + trimmedEnvelopes |= UpdateEnvelopes(&(m_SndFile.Instruments[i]->PanEnv)); + trimmedEnvelopes |= UpdateEnvelopes(&(m_SndFile.Instruments[i]->PitchEnv)); } - if(bTrimmedEnvelopes == true) + if(trimmedEnvelopes & 1) AddToLog("WARNING: Instrument envelopes have been shortened.\n"); + if(trimmedEnvelopes & 2) + AddToLog("WARNING: Instrument envelope release nodes are not supported by the new format.\n"); SetModified(); GetPatternUndo()->ClearUndo(); @@ -397,25 +399,36 @@ return TRUE; } -bool CModDoc::UpdateEnvelopes(INSTRUMENTENVELOPE *mptEnv) -//------------------------------------------------------- +// Trim envelopes and remove release nodes. +// If bit 0 of the return value is set, the envelope has been shortened. +// If bit 1 of the return value is set, the envelope's release node has been removed. +uint8 CModDoc::UpdateEnvelopes(INSTRUMENTENVELOPE *mptEnv) +//-------------------------------------------------------- { // shorten instrument envelope if necessary (for mod conversion) const UINT iEnvMax = m_SndFile.GetModSpecifications().envelopePointsMax; - bool bResult = false; + uint8 result = 0; - #define TRIMENV(i) if(i > iEnvMax) {i = iEnvMax; bResult = true;} + #define TRIMENV(i) if(i > iEnvMax) { i = iEnvMax; result |= 1; } TRIMENV(mptEnv->nNodes); TRIMENV(mptEnv->nLoopStart); TRIMENV(mptEnv->nLoopEnd); TRIMENV(mptEnv->nSustainStart); TRIMENV(mptEnv->nSustainEnd); - if(mptEnv->nReleaseNode != ENV_RELEASE_NODE_UNSET) TRIMENV(mptEnv->nReleaseNode); + if(mptEnv->nReleaseNode != ENV_RELEASE_NODE_UNSET) + { + TRIMENV(mptEnv->nReleaseNode); + if(!m_SndFile.GetModSpecifications().hasReleaseNode) + { + mptEnv->nReleaseNode = ENV_RELEASE_NODE_UNSET; + result |= 2; + } + } #undef TRIMENV - return bResult; + return result; } Modified: trunk/OpenMPT/mptrack/View_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_ins.cpp 2010-07-17 20:34:45 UTC (rev 653) +++ trunk/OpenMPT/mptrack/View_ins.cpp 2010-07-17 22:19:07 UTC (rev 654) @@ -472,6 +472,17 @@ if(envelope == nullptr) return false; if(nPoint < 1 || nPoint > (int)EnvGetLastPoint()) return false; + // Don't allow release nodes in IT/XM. GetDocument()/... nullptr check is done in GetEnvelopePtr, so no need to check twice. + if(!GetDocument()->GetSoundFile()->GetModSpecifications().hasReleaseNode) + { + if(envelope->nReleaseNode != ENV_RELEASE_NODE_UNSET) + { + envelope->nReleaseNode = ENV_RELEASE_NODE_UNSET; + return true; + } + return false; + } + if (envelope->nReleaseNode == nPoint) { envelope->nReleaseNode = ENV_RELEASE_NODE_UNSET; @@ -1619,22 +1630,26 @@ void CViewInstrument::OnRButtonDown(UINT, CPoint pt) //-------------------------------------------------- { - CModDoc *pModDoc = GetDocument(); + const CModDoc *pModDoc = GetDocument(); + if(!pModDoc) return; + const CSoundFile *pSndFile = GetDocument()->GetSoundFile(); + if(!pSndFile) return; + CMenu Menu; if (m_dwStatus & INSSTATUS_DRAGGING) return; if ((pModDoc) && (Menu.LoadMenu(IDR_ENVELOPES))) { CMenu* pSubMenu = Menu.GetSubMenu(0); - if (pSubMenu!=NULL) + if (pSubMenu != NULL) { - CSoundFile *pSndFile = pModDoc->GetSoundFile(); - UINT maxpoint = (pSndFile->m_nType == MOD_TYPE_XM) ? 11 : 24; - UINT lastpoint = EnvGetLastPoint(); m_nDragItem = ScreenToPoint(pt.x, pt.y) + 1; + const UINT maxpoint = (pSndFile->m_nType == MOD_TYPE_XM) ? 11 : 24; + const UINT lastpoint = EnvGetLastPoint(); + const bool forceRelease = !pSndFile->GetModSpecifications().hasReleaseNode && (EnvGetReleaseNode() != ENV_RELEASE_NODE_UNSET); pSubMenu->EnableMenuItem(ID_ENVELOPE_INSERTPOINT, (lastpoint < maxpoint) ? MF_ENABLED : MF_GRAYED); pSubMenu->EnableMenuItem(ID_ENVELOPE_REMOVEPOINT, ((m_nDragItem) && (lastpoint > 0)) ? MF_ENABLED : MF_GRAYED); pSubMenu->EnableMenuItem(ID_ENVELOPE_CARRY, (pSndFile->GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT)) ? MF_ENABLED : MF_GRAYED); - pSubMenu->EnableMenuItem(ID_ENVELOPE_TOGGLERELEASENODE, (pSndFile->GetType() & (MOD_TYPE_IT|MOD_TYPE_MPT) && m_nEnv == ENV_VOLUME) ? MF_ENABLED : MF_GRAYED); + pSubMenu->EnableMenuItem(ID_ENVELOPE_TOGGLERELEASENODE, ((pSndFile->GetModSpecifications().hasReleaseNode && m_nEnv == ENV_VOLUME) || forceRelease) ? MF_ENABLED : MF_GRAYED); pSubMenu->CheckMenuItem(ID_ENVELOPE_SETLOOP, (EnvGetLoop()) ? MF_CHECKED : MF_UNCHECKED); pSubMenu->CheckMenuItem(ID_ENVELOPE_SUSTAIN, (EnvGetSustain()) ? MF_CHECKED : MF_UNCHECKED); pSubMenu->CheckMenuItem(ID_ENVELOPE_CARRY, (EnvGetCarry()) ? MF_CHECKED : MF_UNCHECKED); Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-07-17 20:34:45 UTC (rev 653) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-07-17 22:19:07 UTC (rev 654) @@ -557,7 +557,7 @@ public: // for Editing CModDoc* m_pModDoc; - UINT m_nType; + MODTYPE m_nType; CHANNELINDEX m_nChannels; SAMPLEINDEX m_nSamples; INSTRUMENTINDEX m_nInstruments; Modified: trunk/OpenMPT/soundlib/mod_specifications.h =================================================================== --- trunk/OpenMPT/soundlib/mod_specifications.h 2010-07-17 20:34:45 UTC (rev 653) +++ trunk/OpenMPT/soundlib/mod_specifications.h 2010-07-17 22:19:07 UTC (rev 654) @@ -15,7 +15,7 @@ bool HasVolCommand(MODCOMMAND::VOLCMD volcmd) const; bool HasCommand(MODCOMMAND::COMMAND cmd) const; - //NOTE: If changing order, update all initializations below. + // NOTE: If changing order, update all initializations below. char fileExtension[6]; // File extension without dot. MODCOMMAND::NOTE noteMin; // Minimum note index (index starts from 1) MODCOMMAND::NOTE noteMax; // Maximum note index (index starts from 1) @@ -30,11 +30,11 @@ TEMPO tempoMax; ROWINDEX patternRowsMin; ROWINDEX patternRowsMax; - uint16 modNameLengthMax; //Meaning 'usable letters', possible null character is not included. - uint16 sampleNameLengthMax; //Dito - uint16 sampleFilenameLengthMax; //Dito - uint16 instrNameLengthMax; //Dito - uint16 instrFilenameLengthMax; //Dito + uint16 modNameLengthMax; // Meaning 'usable letters', possible null character is not included. + uint16 sampleNameLengthMax; // Dito + uint16 sampleFilenameLengthMax; // Dito + uint16 instrNameLengthMax; // Dito + uint16 instrFilenameLengthMax; // Dito SAMPLEINDEX samplesMax; INSTRUMENTINDEX instrumentsMax; BYTE defaultMixLevels; @@ -43,6 +43,7 @@ UINT speedMax; // Maximum ticks per frame bool hasComments; // True if format has a comments field UINT envelopePointsMax; // Maximum number of points of each envelope + bool hasReleaseNode; // Envelope release node char commands[MAX_EFFECTS + 1]; // An array holding all commands this format supports; commands that are not supported are marked with "?" char volcommands[MAX_VOLCMDS + 1]; // dito, but for volume column bool hasIgnoreIndex; // Does "+++" pattern exist? @@ -61,33 +62,34 @@ NOTE: If changing limits, see whether: -savefile format and GUI methods can handle new values(might not be a small task :). */ - "MPTm", //File extension - 1, //Minimum note index - NOTE_MAX, //Maximum note index - true, //Has notecut. - true, //Has noteoff. - true, //Has notefade. - 4000, //Pattern max. - 4000, //Order max. - 1, //Channel min - 127, //Channel max - 32, //Min tempo - 512, //Max tempo - 1, //Min pattern rows - 1024, //Max pattern rows - 25, //Max mod name length - 26, //Max sample name length - 12, //Max sample filename length - 26, //Max instrument name length - 12, //Max instrument filename length - 4000, //SamplesMax - 256, //instrumentMax - mixLevels_117RC3, //defaultMixLevels - 200, //Max MIDI mapping directives - 1, //Min Speed - 255, //Max Speed - true, //Has song comments - MAX_ENVPOINTS, //Envelope point count + "MPTm", // File extension + 1, // Minimum note index + NOTE_MAX, // Maximum note index + true, // Has notecut. + true, // Has noteoff. + true, // Has notefade. + 4000, // Pattern max. + 4000, // Order max. + 1, // Channel min + 127, // Channel max + 32, // Min tempo + 512, // Max tempo + 1, // Min pattern rows + 1024, // Max pattern rows + 25, // Max mod name length + 26, // Max sample name length + 12, // Max sample filename length + 26, // Max instrument name length + 12, // Max instrument filename length + 4000, // SamplesMax + 256, // instrumentMax + mixLevels_117RC3, // defaultMixLevels + 200, // Max MIDI mapping directives + 1, // Min Speed + 255, // Max Speed + true, // Has song comments + MAX_ENVPOINTS, // Envelope point count + true, // Has envelope release node " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\:#", // Supported Effects " vpcdabuhlrgfe?o", // Supported Volume Column commands true, // Has "+++" pattern @@ -100,34 +102,35 @@ const CModSpecifications mod = { - //TODO: Set correct values. - "mod", //File extension - 37, //Minimum note index - 108, //Maximum note index - false, //No notecut. - false, //No noteoff. - false, //No notefade. - 64, //Pattern max. - 128, //Order max. - 4, //Channel min - 32, //Channel max - 32, //Min tempo - 255, //Max tempo - 64, //Min pattern rows - 64, //Max pattern rows - 20, //Max mod name length - 22, //Max sample name length - 0, //Max sample filename length - 0, //Max instrument name length - 0, //Max instrument filename length - 31, //SamplesMax - 0, //instrumentMax - mixLevels_original, //defaultMixLevels - 0, //Max MIDI mapping directives - 1, //Min Speed - 31, //Max Speed - false, //No song comments - 0, //No instrument envelopes + // TODO: Set correct values. + "mod", // File extension + 37, // Minimum note index + 108, // Maximum note index + false, // No notecut. + false, // No noteoff. + false, // No notefade. + 64, // Pattern max. + 128, // Order max. + 4, // Channel min + 32, // Channel max + 32, // Min tempo + 255, // Max tempo + 64, // Min pattern rows + 64, // Max pattern rows + 20, // Max mod name length + 22, // Max sample name length + 0, // Max sample filename length + 0, // Max instrument name length + 0, // Max instrument filename length + 31, // SamplesMax + 0, // instrumentMax + mixLevels_original, // defaultMixLevels + 0, // Max MIDI mapping directives + 1, // Min Speed + 31, // Max Speed + false, // No song comments + 0, // No instrument envelopes + false, // No envelope release node " 0123456789ABCD?FF?E???????????????", // Supported Effects " ???????????????", // Supported Volume Column commands false, // Doesn't have "+++" pattern @@ -138,34 +141,35 @@ // MOD with MPT extensions. const CModSpecifications modEx = { - //TODO: Set correct values. - "mod", //File extension - 37, //Minimum note index - 108, //Maximum note index - false, //No notecut. - false, //No noteoff. - false, //No notefade. - 64, //Pattern max. - 128, //Order max. - 4, //Channel min - 32, //Channel max - 32, //Min tempo - 255, //Max tempo - 64, //Min pattern rows - 64, //Max pattern rows - 20, //Max mod name length - 22, //Max sample name length - 0, //Max sample filename length - 0, //Max instrument name length - 0, //Max instrument filename length - 31, //SamplesMax - 0, //instrumentMax - mixLevels_original, //defaultMixLevels - 0, //Max MIDI mapping directives - 1, //Min Speed - 31, //Max Speed - false, //No song comments - 0, //No instrument envelopes + // TODO: Set correct values. + "mod", // File extension + 37, // Minimum note index + 108, // Maximum note index + false, // No notecut. + false, // No noteoff. + false, // No notefade. + 64, // Pattern max. + 128, // Order max. + 4, // Channel min + 32, // Channel max + 32, // Min tempo + 255, // Max tempo + 64, // Min pattern rows + 64, // Max pattern rows + 20, // Max mod name length + 22, // Max sample name length + 0, // Max sample filename length + 0, // Max instrument name length + 0, // Max instrument filename length + 31, // SamplesMax + 0, // instrumentMax + mixLevels_original, // defaultMixLevels + 0, // Max MIDI mapping directives + 1, // Min Speed + 31, // Max Speed + false, // No song comments + 0, // No instrument envelopes + false, // No envelope release node " 0123456789ABCD?FF?E???????????????", // Supported Effects " ???????????????", // Supported Volume Column commands true, // Has "+++" pattern @@ -175,34 +179,35 @@ const CModSpecifications xm = { - //TODO: Set correct values. - "xm", //File extension - 13, //Minimum note index - 108, //Maximum note index - false, //No notecut. - true, //Has noteoff. - false, //No notefade. - 255, //Pattern max. - 255, //Order max. - 1, //Channel min - 32, //Channel max - 32, //Min tempo - 255, //Max tempo - 1, //Min pattern rows - 256, //Max pattern rows - 20, //Max mod name length - 22, //Max sample name length - 0, //Max sample filename length - 22, //Max instrument name length - 0, //Max instrument filename length - 128 * 16, //SamplesMax (actually 16 per instrument) - 128, //instrumentMax - mixLevels_original, //defaultMixLevels - 0, //Max MIDI mapping directives - 1, //Min Speed - 31, //Max Speed - false, //No song comments - 12, //Envelope point count + // TODO: Set correct values. + "xm", // File extension + 13, // Minimum note index + 108, // Maximum note index + false, // No notecut. + true, // Has noteoff. + false, // No notefade. + 255, // Pattern max. + 255, // Order max. + 1, // Channel min + 32, // Channel max + 32, // Min tempo + 255, // Max tempo + 1, // Min pattern rows + 256, // Max pattern rows + 20, // Max mod name length + 22, // Max sample name length + 0, // Max sample filename length + 22, // Max instrument name length + 0, // Max instrument filename length + 128 * 16, // SamplesMax (actually 16 per instrument) + 128, // instrumentMax + mixLevels_original, // defaultMixLevels + 0, // Max MIDI mapping directives + 1, // Min Speed + 31, // Max Speed + false, // No song comments + 12, // Envelope point count + false, // No envelope release node " 0123456789ABCDRFFTE???GHK??XPL????", // Supported Effects " vpcdabuhlrg????", // Supported Volume Column commands false, // Doesn't have "+++" pattern @@ -213,34 +218,35 @@ // XM with MPT extensions const CModSpecifications xmEx = { - //TODO: Set correct values. - "xm", //File extension - 13, //Minimum note index - 108, //Maximum note index - false, //No notecut. - true, //Has noteoff. - false, //No notefade. - 255, //Pattern max. - 256, //Order max. - 1, //Channel min - 127, //Channel max - 32, //Min tempo - 512, //Max tempo - 1, //Min pattern rows - 1024, //Max pattern rows - 20, //Max mod name length - 22, //Max sample name length - 0, //Max sample filename length - 22, //Max instrument name length - 0, //Max instrument filename length - 4000, //SamplesMax (actually 16 per instrument(256*16=4096), but limited to MAX_SAMPLES=4000) - 256, //instrumentMax - mixLevels_117RC3, //defaultMixLevels - 200, //Max MIDI mapping directives - 1, //Min Speed - 31, //Max Speed - true, //Has song comments - 12, //Envelope point count + // TODO: Set correct values. + "xm", // File extension + 13, // Minimum note index + 108, // Maximum note index + false, // No notecut. + true, // Has noteoff. + false, // No notefade. + 255, // Pattern max. + 256, // Order max. + 1, // Channel min + 127, // Channel max + 32, // Min tempo + 512, // Max tempo + 1, // Min pattern rows + 1024, // Max pattern rows + 20, // Max mod name length + 22, // Max sample name length + 0, // Max sample filename length + 22, // Max instrument name length + 0, // Max instrument filename length + 4000, // SamplesMax (actually 16 per instrument(256*16=4096), but limited to MAX_SAMPLES=4000) + 256, // instrumentMax + mixLevels_117RC3, // defaultMixLevels + 200, // Max MIDI mapping directives + 1, // Min Speed + 31, // Max Speed + true, // Has song comments + 12, // Envelope point count + false, // No envelope release node " 0123456789ABCDRFFTE???GHK?YXPLZ\\?#", // Supported Effects " vpcdabuhlrgfe?o", // Supported Volume Column commands true, // Has "+++" pattern @@ -250,34 +256,35 @@ const CModSpecifications s3m = { - //TODO: Set correct values. - "s3m", //File extension - 13, //Minimum note index - 120, //Maximum note index - true, //Has notecut. - false, //No noteoff. - false, //No notefade. - 99, //Pattern max. - 255, //Order max. - 1, //Channel min - 32, //Channel max - 32, //Min tempo - 255, //Max tempo - 64, //Min pattern rows - 64, //Max pattern rows - 27, //Max mod name length - 27, //Max sample name length - 12, //Max sample filename length - 0, //Max instrument name length - 0, //Max instrument filename length - 99, //SamplesMax - 0, //instrumentMax - mixLevels_original, //defaultMixLevels - 0, //Max MIDI mapping directives - 1, //Min Speed - 255, //Max Speed - false, //No song comments - 0, //No instrument envelopes + // TODO: Set correct values. + "s3m", // File extension + 13, // Minimum note index + 120, // Maximum note index + true, // Has notecut. + false, // No noteoff. + false, // No notefade. + 99, // Pattern max. + 255, // Order max. + 1, // Channel min + 32, // Channel max + 32, // Min tempo + 255, // Max tempo + 64, // Min pattern rows + 64, // Max pattern rows + 27, // Max mod name length + 27, // Max sample name length + 12, // Max sample filename length + 0, // Max instrument name length + 0, // Max instrument filename length + 99, // SamplesMax + 0, // instrumentMax + mixLevels_original, // defaultMixLevels + 0, // Max MIDI mapping directives + 1, // Min Speed + 255, // Max Speed + false, // No song comments + 0, // No instrument envelopes + false, // No envelope release node " JFEGHLKRXODB?CQATI?SMNVW?U????????", // Supported Effects " vp?????????????", // Supported Volume Column commands true, // Has "+++" pattern @@ -288,34 +295,35 @@ // S3M with MPT extensions const CModSpecifications s3mEx = { - //TODO: Set correct values. - "s3m", //File extension - 13, //Minimum note index - NOTE_MAX, //Maximum note index - true, //Has notecut. - false, //No noteoff. - false, //No notefade. - 99, //Pattern max. - 255, //Order max. - 1, //Channel min - 32, //Channel max - 32, //Min tempo - 255, //Max tempo - 64, //Min pattern rows - 64, //Max pattern rows - 27, //Max mod name length - 27, //Max sample name length - 12, //Max sample filename length - 0, //Max instrument name length - 0, //Max instrument filename length - 99, //SamplesMax - 0, //instrumentMax - mixLevels_original, //defaultMixLevels - 0, //Max MIDI mapping directives - 1, //Min Speed - 255, //Max Speed - false, //No song comments - 0, //No instrument envelopes + // TODO: Set correct values. + "s3m", // File extension + 13, // Minimum note index + NOTE_MAX, // Maximum note index + true, // Has notecut. + false, // No noteoff. + false, // No notefade. + 99, // Pattern max. + 255, // Order max. + 1, // Channel min + 32, // Channel max + 32, // Min tempo + 255, // Max tempo + 64, // Min pattern rows + 64, // Max pattern rows + 27, // Max mod name length + 27, // Max sample name length + 12, // Max sample filename length + 0, // Max instrument name length + 0, // Max instrument filename length + 99, // SamplesMax + 0, // instrumentMax + mixLevels_original, // defaultMixLevels + 0, // Max MIDI mapping directives + 1, // Min Speed + 255, // Max Speed + false, // No song comments + 0, // No instrument envelopes + false, // No envelope release node " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\?#", // Supported Effects " vp?????????????", // Supported Volume Column commands true, // Has "+++" pattern @@ -325,34 +333,35 @@ const CModSpecifications it = { - //TODO: Set correct values. - "it", //File extension - 1, //Minimum note index - 120, //Maximum note index - true, //Has notecut. - true, //Has noteoff. - true, //Has notefade. - 200, //Pattern max. - 256, //Order max. - 1, //Channel min - 64, //Channel max - 32, //Min tempo - 255, //Max tempo - 1, //Min pattern rows - 200, //Max pattern rows - 25, //Max mod name length - 25, //Max sample name length - 12, //Max sample filename length - 25, //Max instrument name length - 12, //Max instrument filename length - 99, //SamplesMax - 99, //instrumentMax - mixLevels_original, //defaultMixLevels - 0, //Max MIDI mapping directives - 1, //Min Speed - 255, //Max Speed - true, //Has song comments - 25, //Envelope point count + // TODO: Set correct values. + "it", // File extension + 1, // Minimum note index + 120, // Maximum note index + true, // Has notecut. + true, // Has noteoff. + true, // Has notefade. + 200, // Pattern max. + 256, // Order max. + 1, // Channel min + 64, // Channel max + 32, // Min tempo + 255, // Max tempo + 1, // Min pattern rows + 200, // Max pattern rows + 25, // Max mod name length + 25, // Max sample name length + 12, // Max sample filename length + 25, // Max instrument name length + 12, // Max instrument filename length + 99, // SamplesMax + 99, // instrumentMax + mixLevels_original, // defaultMixLevels + 0, // Max MIDI mapping directives + 1, // Min Speed + 255, // Max Speed + true, // Has song comments + 25, // Envelope point count + false, // No envelope release node " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z???", // Supported Effects " vpcdab?h??gfe??", // Supported Volume Column commands true, // Has "+++" pattern @@ -362,34 +371,35 @@ const CModSpecifications itEx = { - //TODO: Set correct values. - "it", //File extension - 1, //Minimum note index - NOTE_MAX, //Maximum note index - true, //Has notecut. - true, //Has noteoff. - true, //Has notefade. - 240, //Pattern max. - 256, //Order max. - 1, //Channel min - 127, //Channel max - 32, //Min tempo - 512, //Max tempo - 1, //Min pattern rows - 1024, //Max pattern rows - 25, //Max mod name length - 25, //Max sample name length - 12, //Max sample filename length - 25, //Max instrument name length - 12, //Max instrument filename length - 4000, //SamplesMax - 256, //instrumentMax - mixLevels_117RC3, //defaultMixLevels - 200, //Max MIDI mapping directives - 1, //Min Speed - 255, //Max Speed - true, //Has song comments - 25, //Envelope point count + // TODO: Set correct values. + "it", // File extension + 1, // Minimum note index + NOTE_MAX, // Maximum note index + true, // Has notecut. + true, // Has noteoff. + true, // Has notefade. + 240, // Pattern max. + 256, // Order max. + 1, // Channel min + 127, // Channel max + 32, // Min tempo + 512, // Max tempo + 1, // Min pattern rows + 1024, // Max pattern rows + 25, // Max mod name length + 25, // Max sample name length + 12, // Max sample filename length + 25, // Max instrument name length + 12, // Max instrument filename length + 4000, // SamplesMax + 256, // instrumentMax + mixLevels_117RC3, // defaultMixLevels + 200, // Max MIDI mapping directives + 1, // Min Speed + 255, // Max Speed + true, // Has song comments + 25, // Envelope point count + false, // No envelope release node " JFEGHLKRXODB?CQATI?SMNVW?UY?P?Z\\?#", // Supported Effects " vpcdab?h??gfe?o", // Supported Volume Column commands true, // Has "+++" pattern @@ -397,7 +407,7 @@ true, // Supports plugins }; -} //namespace ModSpecs +} // namespace ModSpecs This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-18 23:05:26
|
Revision: 657 http://modplug.svn.sourceforge.net/modplug/?rev=657&view=rev Author: saga-games Date: 2010-07-18 23:05:20 +0000 (Sun, 18 Jul 2010) Log Message: ----------- [Fix] Saving XM files with 127 channels (sigh) was broken. [Mod] OpenMPT: Version is now 1.18.02.05 Modified Paths: -------------- trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Load_xm.cpp Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-07-18 22:40:22 UTC (rev 656) +++ trunk/OpenMPT/mptrack/version.h 2010-07-18 23:05:20 UTC (rev 657) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 #define VER_MINOR 02 -#define VER_MINORMINOR 04 +#define VER_MINORMINOR 05 //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_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-18 22:40:22 UTC (rev 656) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-18 23:05:20 UTC (rev 657) @@ -766,7 +766,7 @@ xmheader.restartpos = LittleEndianW(m_nRestartPos); xmheader.channels = (m_nChannels + 1) & 0xFFFE; // avoid odd channel count for FT2 compatibility - if(m_nChannels & 1) bAddChannel = true; + if((m_nChannels & 1) && m_nChannels < MAX_BASECHANNELS) bAddChannel = true; if(bCompatibilityExport && xmheader.channels > 32) xmheader.channels = 32; if(xmheader.channels > MAX_BASECHANNELS) xmheader.channels = MAX_BASECHANNELS; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-26 20:10:00
|
Revision: 661 http://modplug.svn.sourceforge.net/modplug/?rev=661&view=rev Author: saga-games Date: 2010-07-26 20:09:53 +0000 (Mon, 26 Jul 2010) Log Message: ----------- [Fix] Mod Conversion: Extra fine portamento was not converted properly when converting from IT/MPTM/S3M to XM. [Imp] Orderlist: Improved sequence name display in context menu. [Ref] Removed some old, unused code. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_ins.h trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/soundlib/modcommand.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-23 23:58:27 UTC (rev 660) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-26 20:09:53 UTC (rev 661) @@ -727,7 +727,6 @@ ON_COMMAND(IDC_CHECK1, OnSetPanningChanged) ON_COMMAND(IDC_CHECK2, OnEnableCutOff) ON_COMMAND(IDC_CHECK3, OnEnableResonance) -// ON_COMMAND(IDC_CHECK4, OnToggleHighpass) ON_COMMAND(IDC_INSVIEWPLG, TogglePluginEditor) //rewbs.instroVSTi ON_EN_CHANGE(IDC_EDIT_INSTRUMENT, OnInstrumentChanged) ON_EN_CHANGE(IDC_SAMPLE_NAME, OnNameChanged) @@ -792,7 +791,6 @@ DDX_Control(pDX, IDC_CHECK1, m_CheckPanning); DDX_Control(pDX, IDC_CHECK2, m_CheckCutOff); DDX_Control(pDX, IDC_CHECK3, m_CheckResonance); - DDX_Control(pDX, IDC_CHECK4, m_CheckHighpass); DDX_Control(pDX, IDC_SLIDER1, m_SliderVolSwing); DDX_Control(pDX, IDC_SLIDER2, m_SliderPanSwing); DDX_Control(pDX, IDC_SLIDER3, m_SliderCutOff); @@ -1149,7 +1147,6 @@ m_EditPPS.EnableWindow(bITandMPT); m_CheckCutOff.EnableWindow(bITandMPT); m_CheckResonance.EnableWindow(bITandMPT); - m_CheckHighpass.EnableWindow(bITandMPT); m_SliderCutOff.EnableWindow(bITandMPT); m_SliderResonance.EnableWindow(bITandMPT); m_SpinInstrument.SetRange(1, m_pSndFile->m_nInstruments); @@ -1231,7 +1228,6 @@ { m_CheckCutOff.SetCheck((pIns->nIFC & 0x80) ? TRUE : FALSE); m_CheckResonance.SetCheck((pIns->nIFR & 0x80) ? TRUE : FALSE); - //m_CheckHighpass.SetCheck(pIns->nFilterMode); m_SliderVolSwing.SetPos(pIns->nVolSwing); m_SliderPanSwing.SetPos(pIns->nPanSwing); m_SliderResSwing.SetPos(pIns->nResSwing); @@ -2308,40 +2304,7 @@ } } -/* -void CCtrlInstruments::OnToggleHighpass() -//---------------------------------------- -{ - BOOL bHighpass = IsDlgButtonChecked(IDC_CHECK4); - if (!m_pModDoc) { - return; - } - - CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); - MODINSTRUMENT *pIns = pSndFile->Instruments[m_nInstrument]; - - if (pIns) { - if (bHighpass) { - pIns->nFilterMode = FLTMODE_HIGHPASS; - } else { - pIns->nFilterMode = 0; - } - - for (UINT i=0; i<MAX_CHANNELS; i++) { - if (pSndFile->Chn[i].pModInstrument == pIns) { - pSndFile->Chn[i].nFilterMode = pIns->nFilterMode; - } - } - } - m_pSndFile->instrumentModified[m_nInstrument-1] = TRUE; - m_pModDoc->UpdateAllViews(NULL, HINT_INSNAMES, this); - m_pModDoc->SetModified(); - SwitchToView(); - -} -*/ - void CCtrlInstruments::OnVScroll(UINT nCode, UINT nPos, CScrollBar *pSB) //---------------------------------------------------------------------- { Modified: trunk/OpenMPT/mptrack/Ctrl_ins.h =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.h 2010-07-23 23:58:27 UTC (rev 660) +++ trunk/OpenMPT/mptrack/Ctrl_ins.h 2010-07-26 20:09:53 UTC (rev 661) @@ -72,7 +72,7 @@ CSpinButtonCtrl m_SpinMidiPR, m_SpinPPS, m_SpinMidiBK; CComboBox m_ComboNNA, m_ComboDCT, m_ComboDCA, m_ComboPPC, m_CbnMidiCh, m_CbnMixPlug, m_CbnResampling, m_CbnFilterMode, m_CbnPluginVelocityHandling, m_CbnPluginVolumeHandling; CEdit m_EditName, m_EditFileName, m_EditGlobalVol, m_EditPanning, m_EditPPS; - CButton m_CheckPanning, m_CheckCutOff, m_CheckResonance, m_CheckHighpass; + CButton m_CheckPanning, m_CheckCutOff, m_CheckResonance; CSliderCtrl m_SliderVolSwing, m_SliderPanSwing, m_SliderCutSwing, m_SliderResSwing, m_SliderCutOff, m_SliderResonance; CNoteMapWnd m_NoteMap; @@ -163,7 +163,6 @@ afx_msg void OnEnableCutOff(); afx_msg void OnEnableResonance(); - //afx_msg void OnToggleHighpass(); afx_msg void OnEditSampleMap(); afx_msg void TogglePluginEditor(); //rewbs.instroVSTi afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM); //rewbs.customKeys Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2010-07-23 23:58:27 UTC (rev 660) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2010-07-26 20:09:53 UTC (rev 661) @@ -1068,7 +1068,10 @@ for(SEQUENCEINDEX i = 0; i < numSequences; i++) { CString str; - str.Format(TEXT("%u: %s"), i, (LPCTSTR)pSndFile->Order.GetSequence(i).m_sName); + if(pSndFile->Order.GetSequence(i).m_sName.IsEmpty()) + str.Format(TEXT("Sequence %u"), i); + else + str.Format(TEXT("%u: %s"), i, (LPCTSTR)pSndFile->Order.GetSequence(i).m_sName); const UINT flags = (pSndFile->Order.GetCurrentSequenceIndex() == i) ? MF_STRING|MF_CHECKED : MF_STRING; AppendMenu(menuSequence, flags, ID_SEQUENCE_ITEM + i, str); } Modified: trunk/OpenMPT/soundlib/modcommand.cpp =================================================================== --- trunk/OpenMPT/soundlib/modcommand.cpp 2010-07-23 23:58:27 UTC (rev 660) +++ trunk/OpenMPT/soundlib/modcommand.cpp 2010-07-26 20:09:53 UTC (rev 661) @@ -230,8 +230,15 @@ } else if (m->param >= 0xE0) { - m->command = CMD_MODCMDEX; - m->param = (((m->param & 0x0F)+3) >> 2) | 0x10; + if(newTypeIsXM) + { + m->command = CMD_XFINEPORTAUPDOWN; + m->param = 0x10 | (m->param & 0x0F); + } else + { + m->command = CMD_MODCMDEX; + m->param = (((m->param & 0x0F) + 3) >> 2) | 0x10; + } } else m->command = CMD_PORTAMENTOUP; break; case CMD_PORTAMENTODOWN: @@ -242,8 +249,15 @@ } else if (m->param >= 0xE0) { - m->command = CMD_MODCMDEX; - m->param = (((m->param & 0x0F)+3) >> 2) | 0x20; + if(newTypeIsXM) + { + m->command = CMD_XFINEPORTAUPDOWN; + m->param = 0x20 | (m->param & 0x0F); + } else + { + m->command = CMD_MODCMDEX; + m->param = (((m->param & 0x0F) + 3) >> 2) | 0x20; + } } else m->command = CMD_PORTAMENTODOWN; break; case CMD_SPEED: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-28 23:20:04
|
Revision: 664 http://modplug.svn.sourceforge.net/modplug/?rev=664&view=rev Author: saga-games Date: 2010-07-28 23:19:58 +0000 (Wed, 28 Jul 2010) Log Message: ----------- [Fix] XM Loader: Compatibility flag was set too early. [Imp] Instrument Editor: Sample Map accepts various new shortcuts now. [Mod] Updated DE_jojo.mkb to include new shortcuts, remapped a few others (for IT-style). Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/Ctrl_ins.h trunk/OpenMPT/mptrack/KeyConfigDlg.cpp trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb trunk/OpenMPT/soundlib/Load_xm.cpp Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2010-07-28 23:19:58 UTC (rev 664) @@ -125,7 +125,7 @@ DefineKeyCommand(kcCopySelectOff, 1053, kcHidden, kcNoDummy, _T("Copy deselect key")); DefineKeyCommand(kcNextPattern, 1054, kcVisible, kcNoDummy, _T("Next pattern")); DefineKeyCommand(kcPrevPattern, 1055, kcVisible, kcNoDummy, _T("Previous pattern")); - //DefineKeyCommand(kcPrevPattern, 1056, kcVisible, kcNoDummy, _T("Wipe selection")); + //DefineKeyCommand(kcClearSelection, 1056, kcVisible, kcNoDummy, _T("Wipe selection")); DefineKeyCommand(kcClearRow, 1057, kcVisible, kcNoDummy, _T("Clear row")); DefineKeyCommand(kcClearField, 1058, kcVisible, kcNoDummy, _T("Clear field")); DefineKeyCommand(kcClearRowStep, 1059, kcVisible, kcNoDummy, _T("Clear row and step")); @@ -588,6 +588,17 @@ DefineKeyCommand(kcVSTGUIToggleRecordParams, 1839, kcVisible, kcNoDummy, _T("Toggle parameter recording")); DefineKeyCommand(kcVSTGUIToggleSendKeysToPlug, 1840, kcVisible, kcNoDummy, _T("Pass key presses to plugin")); DefineKeyCommand(kcVSTGUIBypassPlug, 1841, kcVisible, kcNoDummy, _T("Bypass plugin")); + DefineKeyCommand(kcInsNoteMapTransposeDown, 1842, kcVisible, kcNoDummy, _T("Transpose -1 (note map)")); + DefineKeyCommand(kcInsNoteMapTransposeUp, 1843, kcVisible, kcNoDummy, _T("Transpose +1 (note map)")); + DefineKeyCommand(kcInsNoteMapTransposeOctDown, 1844, kcVisible, kcNoDummy, _T("Transpose -12 (note map)")); + DefineKeyCommand(kcInsNoteMapTransposeOctUp, 1845, kcVisible, kcNoDummy, _T("Transpose +12 (note map)")); + DefineKeyCommand(kcInsNoteMapCopyCurrentNote, 1846, kcVisible, kcNoDummy, _T("Map all notes to selected note")); + DefineKeyCommand(kcInsNoteMapCopyCurrentSample, 1847, kcVisible, kcNoDummy, _T("Map all notes to selected sample")); + DefineKeyCommand(kcInsNoteMapReset, 1848, kcVisible, kcNoDummy, _T("Reset note mapping")); + DefineKeyCommand(kcInsNoteMapEditSample, 1849, kcVisible, kcNoDummy, _T("Edit current sample")); + DefineKeyCommand(kcInsNoteMapEditSampleMap, 1850, kcVisible, kcNoDummy, _T("Edit sample map")); + DefineKeyCommand(kcInstrumentCtrlDuplicate, 1851, kcVisible, kcNoDummy, _T("Duplicate instrument")); + // Add new key commands here. #ifdef _DEBUG for(size_t i = 0; i < kcNumCommands; i++) Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/mptrack/CommandSet.h 2010-07-28 23:19:58 UTC (rev 664) @@ -573,7 +573,17 @@ kcInstrumentCtrlLoad=kcStartInstrumentCtrlMisc, kcInstrumentCtrlSave, kcInstrumentCtrlNew, - kcEndInstrumentCtrlMisc=kcInstrumentCtrlNew, + kcInstrumentCtrlDuplicate, + kcInsNoteMapEditSampleMap, + kcInsNoteMapEditSample, + kcInsNoteMapCopyCurrentNote, + kcInsNoteMapCopyCurrentSample, + kcInsNoteMapReset, + kcInsNoteMapTransposeUp, + kcInsNoteMapTransposeDown, + kcInsNoteMapTransposeOctUp, + kcInsNoteMapTransposeOctDown, + kcEndInstrumentCtrlMisc=kcInsNoteMapTransposeOctDown, kcStartSampleMisc, kcSampleLoad=kcStartSampleMisc, Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2010-07-28 23:19:58 UTC (rev 664) @@ -61,6 +61,12 @@ if (ih->KeyEvent(ctx, nChar, nRepCnt, nFlags, kT) != kcNull) return true; // Mapped to a command, no need to pass message on. + + // a bit of a hack... + ctx = (InputTargetContext)(kCtxCtrlInstruments); + + if (ih->KeyEvent(ctx, nChar, nRepCnt, nFlags, kT) != kcNull) + return true; // Mapped to a command, no need to pass message on. } } @@ -154,7 +160,7 @@ dc.IntersectClipRect(&rcClient); if ((m_pModDoc) && (m_cxFont > 0) && (m_cyFont > 0)) { - BOOL bFocus = (::GetFocus() == m_hWnd) ? TRUE : FALSE; + bool bFocus = (::GetFocus() == m_hWnd); CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); MODINSTRUMENT *pIns = pSndFile->Instruments[m_nInstrument]; CHAR s[64]; @@ -165,7 +171,7 @@ int ypaint = 0; for (int ynote=0; ynote<nNotes; ynote++, ypaint+=m_cyFont, nPos++) { - BOOL bHighLight; + bool bHighLight; // Note s[0] = 0; @@ -176,7 +182,7 @@ rect.SetRect(0, ypaint, m_cxFont, ypaint+m_cyFont); DrawButtonRect(hdc, &rect, s, FALSE, FALSE); // Mapped Note - bHighLight = ((bFocus) && (nPos == (int)m_nNote) /*&& (!m_bIns)*/) ? TRUE : FALSE; + bHighLight = ((bFocus) && (nPos == (int)m_nNote) /*&& (!m_bIns)*/); rect.left = rect.right; rect.right = m_cxFont*2-1; strcpy(s, "..."); @@ -203,7 +209,7 @@ dc.SetTextColor((bHighLight) ? colorTextSel : colorText); dc.DrawText(s, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER); // Sample - bHighLight = ((bFocus) && (nPos == (int)m_nNote) /*&& (m_bIns)*/) ? TRUE : FALSE; + bHighLight = ((bFocus) && (nPos == (int)m_nNote) /*&& (m_bIns)*/); rect.left = rcClient.left + m_cxFont*2+3; rect.right = rcClient.right; strcpy(s, " .."); @@ -254,15 +260,18 @@ void CNoteMapWnd::OnLButtonDown(UINT, CPoint pt) //---------------------------------------------- { - if ((pt.x >= m_cxFont) && (pt.x < m_cxFont*2) && (m_bIns)) { - m_bIns = FALSE; + if ((pt.x >= m_cxFont) && (pt.x < m_cxFont*2) && (m_bIns)) + { + m_bIns = false; InvalidateRect(NULL, FALSE); } - if ((pt.x > m_cxFont*2) && (pt.x <= m_cxFont*3) && (!m_bIns)) { - m_bIns = TRUE; + if ((pt.x > m_cxFont*2) && (pt.x <= m_cxFont*3) && (!m_bIns)) + { + m_bIns = true; InvalidateRect(NULL, FALSE); } - if ((pt.x >= 0) && (m_cyFont)) { + if ((pt.x >= 0) && (m_cyFont)) + { CRect rcClient; GetClientRect(&rcClient); int nNotes = (rcClient.bottom + m_cyFont - 1) / m_cyFont; @@ -290,9 +299,11 @@ CHAR s[64]; CSoundFile *pSndFile; MODINSTRUMENT *pIns; + CInputHandler* ih = CMainFrame::GetInputHandler(); pSndFile = m_pModDoc->GetSoundFile(); pIns = pSndFile->Instruments[m_nInstrument]; + if (pIns) { HMENU hMenu = ::CreatePopupMenu(); @@ -300,7 +311,7 @@ if (hMenu) { - AppendMenu(hMenu, MF_STRING, ID_INSTRUMENT_SAMPLEMAP, "Edit Sample &Map"); + AppendMenu(hMenu, MF_STRING, ID_INSTRUMENT_SAMPLEMAP, "Edit Sample &Map\t" + ih->GetKeyTextFromCommand(kcInsNoteMapEditSampleMap)); if (hSubMenu) { BYTE smpused[(MAX_SAMPLES+7)/8]; @@ -321,24 +332,24 @@ AppendMenu(hSubMenu, MF_STRING, ID_NOTEMAP_EDITSAMPLE+j, s); } } - AppendMenu(hMenu, MF_POPUP, (UINT)hSubMenu, "&Edit Sample"); + AppendMenu(hMenu, MF_POPUP, (UINT)hSubMenu, "&Edit Sample\t" + ih->GetKeyTextFromCommand(kcInsNoteMapEditSample)); AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); } - wsprintf(s, "Map all notes to &sample %d", pIns->Keyboard[m_nNote]); + wsprintf(s, "Map all notes to &sample %d\t" + ih->GetKeyTextFromCommand(kcInsNoteMapCopyCurrentSample), pIns->Keyboard[m_nNote]); AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_COPY_SMP, s); if(pSndFile->GetType() != MOD_TYPE_XM) { if(pIns->NoteMap[m_nNote] < NOTE_MIN_SPECIAL) - wsprintf(s, "Map all ¬es to %s", pSndFile->GetNoteName(pIns->NoteMap[m_nNote], m_nInstrument).c_str()); + wsprintf(s, "Map all ¬es to %s\t" + ih->GetKeyTextFromCommand(kcInsNoteMapCopyCurrentNote), pSndFile->GetNoteName(pIns->NoteMap[m_nNote], m_nInstrument).c_str()); else - wsprintf(s, "Map all ¬es to %s", szSpecialNoteNames[pIns->NoteMap[m_nNote] - NOTE_MIN_SPECIAL]); + wsprintf(s, "Map all ¬es to %s\t" + ih->GetKeyTextFromCommand(kcInsNoteMapCopyCurrentNote), szSpecialNoteNames[pIns->NoteMap[m_nNote] - NOTE_MIN_SPECIAL]); AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_COPY_NOTE, s); - AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_TRANS_UP, "Transpose map &up"); - AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_TRANS_DOWN, "Transpose map &down"); + AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_TRANS_UP, "Transpose map &up\t" + ih->GetKeyTextFromCommand(kcInsNoteMapTransposeUp)); + AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_TRANS_DOWN, "Transpose map &down\t" + ih->GetKeyTextFromCommand(kcInsNoteMapTransposeDown)); } - AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_RESET, "&Reset note mapping"); - AppendMenu(hMenu, MF_STRING, ID_INSTRUMENT_DUPLICATE, "Duplicate &Instrument\tShift+New"); + AppendMenu(hMenu, MF_STRING, ID_NOTEMAP_RESET, "&Reset note mapping\t" + ih->GetKeyTextFromCommand(kcInsNoteMapReset)); + AppendMenu(hMenu, MF_STRING, ID_INSTRUMENT_DUPLICATE, "Duplicate &Instrument\t" + ih->GetKeyTextFromCommand(kcInstrumentCtrlDuplicate)); SetMenuDefaultItem(hMenu, ID_INSTRUMENT_SAMPLEMAP, FALSE); ClientToScreen(&pt); ::TrackPopupMenu(hMenu, TPM_LEFTALIGN|TPM_RIGHTBUTTON, pt.x, pt.y, 0, m_hWnd, NULL); @@ -411,6 +422,7 @@ MODINSTRUMENT *pIns; pSndFile = m_pModDoc->GetSoundFile(); + if(pSndFile == nullptr) return; pIns = pSndFile->Instruments[m_nInstrument]; if (pIns) { @@ -503,11 +515,15 @@ return NULL; CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); + CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + MODINSTRUMENT *pIns = nullptr; + if(pSndFile) + { + pIns = pSndFile->Instruments[m_nInstrument]; + } - //Handle notes + // Handle notes - - if (wParam>=kcInsNoteMapStartNotes && wParam<=kcInsNoteMapEndNotes) { //Special case: number keys override notes if we're in the sample # column. @@ -524,6 +540,26 @@ StopNote(m_nPlayingNote); return wParam; } + + // Other shortcuts + + switch(wParam) + { + case kcInsNoteMapTransposeDown: MapTranspose(-1); return wParam; + case kcInsNoteMapTransposeUp: MapTranspose(1); return wParam; + case kcInsNoteMapTransposeOctDown: MapTranspose(-12); return wParam; + case kcInsNoteMapTransposeOctUp: MapTranspose(12); return wParam; + + case kcInsNoteMapCopyCurrentSample: OnMapCopySample(); return wParam; + case kcInsNoteMapCopyCurrentNote: OnMapCopyNote(); return wParam; + case kcInsNoteMapReset: OnMapReset(); return wParam; + + case kcInsNoteMapEditSample: if(pIns) OnEditSample(pIns->Keyboard[m_nNote] + ID_NOTEMAP_EDITSAMPLE); return wParam; + case kcInsNoteMapEditSampleMap: OnEditSampleMap(); return wParam; + + // Parent shortcuts (also displayed in context menu of this control) + case kcInstrumentCtrlDuplicate: OnInstrumentDuplicate(); return wParam; + } return NULL; } @@ -538,11 +574,11 @@ if (!m_bIns && (pSndFile->m_nType & (MOD_TYPE_IT|MOD_TYPE_MPT))) { UINT n = pIns->NoteMap[m_nNote]; - BOOL bOk = FALSE; + bool bOk = false; if ((note > 0) && (note <= NOTE_MAX)) { n = note; - bOk = TRUE; + bOk = true; } if (n != pIns->NoteMap[m_nNote]) { @@ -565,26 +601,30 @@ { CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); MODINSTRUMENT *pIns = pSndFile->Instruments[m_nInstrument]; - if ((pIns) && (m_nNote < NOTE_MAX)) { + if ((pIns) && (m_nNote < NOTE_MAX)) + { - if ((m_bIns) && (((c >= '0') && (c <= '9')) || (c == ' '))) { //in sample # column - + if ((m_bIns) && (((c >= '0') && (c <= '9')) || (c == ' '))) //in sample # column + { UINT n = m_nOldIns; - if (c != ' ') { - n = (10*pIns->Keyboard[m_nNote] + (c - '0')) % 10000; + if (c != ' ') + { + n = (10 * pIns->Keyboard[m_nNote] + (c - '0')) % 10000; if ((n >= MAX_SAMPLES) || ((pSndFile->m_nSamples < 1000) && (n >= 1000))) n = (n % 1000); if ((n >= MAX_SAMPLES) || ((pSndFile->m_nSamples < 100) && (n >= 100))) n = (n % 100); else if ((n > 31) && (pSndFile->m_nSamples < 32) && (n % 10)) n = (n % 10); } - if (n != pIns->Keyboard[m_nNote]) { + if (n != pIns->Keyboard[m_nNote]) + { pIns->Keyboard[m_nNote] = n; m_pModDoc->SetModified(); InvalidateRect(NULL, FALSE); PlayNote(m_nNote+1); } - if (c == ' ') { + if (c == ' ') + { if (m_nNote < NOTE_MAX - 1) m_nNote++; InvalidateRect(NULL, FALSE); PlayNote(m_nNote); @@ -592,27 +632,30 @@ return true; } - else if ((!m_bIns) && (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT))) { //in note column - + else if ((!m_bIns) && (pSndFile->m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT))) //in note column + { UINT n = pIns->NoteMap[m_nNote]; - if ((c >= '0') && (c <= '9')) { - if (n) { + if ((c >= '0') && (c <= '9')) + { + if (n) n = ((n-1) % 12) + (c-'0')*12 + 1; - } else { + else n = (m_nNote % 12) + (c-'0')*12 + 1; - } - } else if (c == ' ') { + } else if (c == ' ') + { n = (m_nOldNote) ? m_nOldNote : m_nNote+1; } - if (n != pIns->NoteMap[m_nNote]) { + if (n != pIns->NoteMap[m_nNote]) + { pIns->NoteMap[m_nNote] = n; m_pModDoc->SetModified(); InvalidateRect(NULL, FALSE); } - if (c == ' ') { + if (c == ' ') + { SetCurrentNote(m_nNote+1); } @@ -627,7 +670,7 @@ bool CNoteMapWnd::HandleNav(WPARAM k) //------------------------------------ { - BOOL bRedraw = FALSE; + bool bRedraw = false; //HACK: handle numpad (convert numpad number key to normal number key) if ((k >= VK_NUMPAD0) && (k <= VK_NUMPAD9)) return HandleChar(k-VK_NUMPAD0+'0'); @@ -635,26 +678,26 @@ switch(k) { case VK_RIGHT: - if (!m_bIns) { m_bIns = TRUE; bRedraw = TRUE; } else - if (m_nNote < NOTE_MAX - 1) { m_nNote++; m_bIns = FALSE; bRedraw = TRUE; } + if (!m_bIns) { m_bIns = true; bRedraw = true; } else + if (m_nNote < NOTE_MAX - 1) { m_nNote++; m_bIns = false; bRedraw = true; } break; case VK_LEFT: - if (m_bIns) { m_bIns = FALSE; bRedraw = TRUE; } else - if (m_nNote) { m_nNote--; m_bIns = TRUE; bRedraw = TRUE; } + if (m_bIns) { m_bIns = false; bRedraw = true; } else + if (m_nNote) { m_nNote--; m_bIns = true; bRedraw = true; } break; case VK_UP: - if (m_nNote > 0) { m_nNote--; bRedraw = TRUE; } + if (m_nNote > 0) { m_nNote--; bRedraw = true; } break; case VK_DOWN: - if (m_nNote < NOTE_MAX - 1) { m_nNote++; bRedraw = TRUE; } + if (m_nNote < NOTE_MAX - 1) { m_nNote++; bRedraw = true; } break; case VK_PRIOR: - if (m_nNote > 3) { m_nNote-=3; bRedraw = TRUE; } else - if (m_nNote > 0) { m_nNote = 0; bRedraw = TRUE; } + if (m_nNote > 3) { m_nNote -= 3; bRedraw = true; } else + if (m_nNote > 0) { m_nNote = 0; bRedraw = true; } break; case VK_NEXT: - if (m_nNote+3 < NOTE_MAX) { m_nNote+=3; bRedraw = TRUE; } else - if (m_nNote < NOTE_MAX - 1) { m_nNote = NOTE_MAX - 1; bRedraw = TRUE; } + if (m_nNote+3 < NOTE_MAX) { m_nNote += 3; bRedraw = true; } else + if (m_nNote < NOTE_MAX - 1) { m_nNote = NOTE_MAX - 1; bRedraw = true; } break; case VK_TAB: return true; @@ -2528,6 +2571,8 @@ case kcInstrumentCtrlLoad: OnInstrumentOpen(); return wParam; case kcInstrumentCtrlSave: OnInstrumentSave(); return wParam; case kcInstrumentCtrlNew: OnInstrumentNew(); return wParam; + + case kcInstrumentCtrlDuplicate: OnInstrumentDuplicate(); return wParam; } return 0; Modified: trunk/OpenMPT/mptrack/Ctrl_ins.h =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.h 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/mptrack/Ctrl_ins.h 2010-07-28 23:19:58 UTC (rev 664) @@ -13,7 +13,8 @@ protected: CModDoc *m_pModDoc; CCtrlInstruments *m_pParent; - UINT m_nInstrument, m_nNote, m_bIns, m_nOldNote, m_nOldIns; + UINT m_nInstrument, m_nNote, m_nOldNote, m_nOldIns; + bool m_bIns; int m_nPlayingNote; HFONT m_hFont; int m_cxFont, m_cyFont; @@ -23,7 +24,18 @@ void MapTranspose(int nAmount); public: - CNoteMapWnd() { m_nPlayingNote=-1; m_nNote = NOTE_MIDDLEC - 1; m_pModDoc = NULL; m_nInstrument = 0; m_bIns = FALSE; m_cxFont = m_cyFont = 0; m_hFont = NULL; m_nOldNote = m_nOldIns = 0; m_pParent = NULL; } + CNoteMapWnd() + { + m_nPlayingNote = -1; + m_nNote = NOTE_MIDDLEC - 1; + m_pModDoc = nullptr; + m_nInstrument = 0; + m_bIns = false; + m_cxFont = m_cyFont = 0; + m_hFont = NULL; + m_nOldNote = m_nOldIns = 0; + m_pParent = NULL; + } BOOL SetCurrentInstrument(CModDoc *pModDoc, UINT nIns); BOOL SetCurrentNote(UINT nNote); VOID Init(CCtrlInstruments *pParent) { m_pParent = pParent; } Modified: trunk/OpenMPT/mptrack/KeyConfigDlg.cpp =================================================================== --- trunk/OpenMPT/mptrack/KeyConfigDlg.cpp 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/mptrack/KeyConfigDlg.cpp 2010-07-28 23:19:58 UTC (rev 664) @@ -304,11 +304,13 @@ commandCategories.Add(*newCat); delete newCat; - newCat = new CommandCategory(" Instrument [Top]", kCtxCtrlInstruments); + newCat = new CommandCategory(" Instrument Editor", kCtxCtrlInstruments); + for (int c=kcStartInstrumentCtrlMisc; c<=kcEndInstrumentCtrlMisc; c++) + newCat->commands.Add(c); commandCategories.Add(*newCat); delete newCat; - newCat = new CommandCategory(" Instrument Editor", kCtxViewInstruments); + newCat = new CommandCategory(" Envelope Editor", kCtxViewInstruments); for (int c=kcStartInstrumentMisc; c<=kcEndInstrumentMisc; c++) newCat->commands.Add(c); commandCategories.Add(*newCat); @@ -355,7 +357,7 @@ // Fills command list and automatically selects first command. void COptionsKeyboard::OnCategorySelChanged() -//---------------------------------------- +//------------------------------------------- { CommandID nCmd = (CommandID)m_lbnCommandKeys.GetItemData( m_lbnCommandKeys.GetCurSel() ); int nCat = m_cmbCategory.GetItemData( m_cmbCategory.GetCurSel() ); @@ -385,7 +387,7 @@ // Fills key choice list and automatically selects first key choice void COptionsKeyboard::OnCommandKeySelChanged() -//---------------------------------------- +//--------------------------------------------- { CommandID nCmd = (CommandID)m_lbnCommandKeys.GetItemData( m_lbnCommandKeys.GetCurSel() ); CString str; Modified: trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/DE_jojo.mkb 2010-07-28 23:19:58 UTC (rev 664) @@ -31,15 +31,17 @@ 0:1365:2:70:1 //Find: Ctrl+F (KeyDown) 0:1366:0:114:1 //Find Next: F3 (KeyDown) 0:1021:4:71:1 //View General: Alt+G (KeyDown) +0:1021:0:112:1 //View General: F1 (KeyDown) 0:1022:4:80:1 //View Pattern: Alt+P (KeyDown) +0:1022:0:113:1 //View Pattern: F2 (KeyDown) 0:1023:4:83:1 //View Samples: Alt+S (KeyDown) 0:1024:4:78:1 //View Instruments: Alt+N (KeyDown) +0:1024:0:115:1 //View Instruments: F4 (KeyDown) 0:1025:1:120:1 //View Comments: Shift+F9 (KeyDown) 0:1025:4:67:1 //View Comments: Alt+C (KeyDown) 0:1368:2:113:1 //Toggle Tree View: Ctrl+F2 (KeyDown) 0:1369:2:112:1 //View Options: Ctrl+F1 (KeyDown) -0:1781:2:114:1 //View MIDI mapping: Ctrl+F3 (KeyDown) -0:1370:0:112:1 //Help (to do): F1 (KeyDown) +0:1781:1:112:1 //View MIDI mapping: Shift+F1 (KeyDown) 0:1032:2:111:5 //Previous instrument: Ctrl+ (ZEHNERTASTATUR) (KeyDown|KeyHold) 0:1032:2:38:5 //Previous instrument: Ctrl+NACH-OBEN (KeyDown|KeyHold) 0:1033:2:106:5 //Next instrument: Ctrl+ (ZEHNERTASTATUR) (KeyDown|KeyHold) @@ -85,6 +87,7 @@ 2:1772:2:93:1 //Show pattern properties window: Ctrl+ANWENDUNG (KeyDown) 2:1819:2:69:1 //Split Keyboard Settings dialog: Ctrl+E (KeyDown) 2:1780:2:80:1 //Show playback time at current row: Ctrl+P (KeyDown) +2:1005:2:85:1 //Mute current channel: Ctrl+U (KeyDown) 2:1786:2:82:1 //Reset channel: Ctrl+R (KeyDown) 2:1007:2:81:5 //Transpose +1: Ctrl+Q (KeyDown|KeyHold) 2:1008:2:65:5 //Transpose -1: Ctrl+A (KeyDown|KeyHold) @@ -317,6 +320,16 @@ //----( Sample Context [top] (16) )------------ //----( Instrument Context [top] (17) )------------ +17:1851:2:68:1 //Duplicate instrument: Ctrl+D (KeyDown) +17:1850:3:69:1 //Edit sample map: Shift+Ctrl+E (KeyDown) +17:1849:2:69:1 //Edit current sample: Ctrl+E (KeyDown) +17:1846:3:77:1 //Map all notes to selected note: Shift+Ctrl+M (KeyDown) +17:1847:2:77:1 //Map all notes to selected sample: Ctrl+M (KeyDown) +17:1848:2:82:1 //Reset note mapping: Ctrl+R (KeyDown) +17:1843:2:81:1 //Transpose +1 (note map): Ctrl+Q (KeyDown) +17:1842:2:65:1 //Transpose -1 (note map): Ctrl+A (KeyDown) +17:1845:3:81:1 //Transpose +12 (note map): Shift+Ctrl+Q (KeyDown) +17:1844:3:65:1 //Transpose -12 (note map): Shift+Ctrl+A (KeyDown) //----( Comments Context [top] (18) )------------ Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-28 18:28:58 UTC (rev 663) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-07-28 23:19:58 UTC (rev 664) @@ -245,8 +245,6 @@ UINT unused_samples; // dito bool bMadeWithModPlug = false, bProbablyMadeWithModPlug = false, bProbablyMPT109 = false, bIsFT2 = false; - // set this here already because XMs compressed with BoobieSqueezer will exit the function early - SetModFlag(MSF_COMPATIBLE_PLAY, true); m_nChannels = 0; if ((!lpStream) || (dwMemLength < 0xAA)) return false; // the smallest XM I know is 174 Bytes @@ -292,6 +290,9 @@ dwMemPos = xmheader.size + 60; + // set this here already because XMs compressed with BoobieSqueezer will exit the function early + SetModFlag(MSF_COMPATIBLE_PLAY, true); + if(xmheader.xmversion >= 0x0104) { if (dwMemPos + 8 >= dwMemLength) return true; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-07-29 13:43:15
|
Revision: 665 http://modplug.svn.sourceforge.net/modplug/?rev=665&view=rev Author: saga-games Date: 2010-07-29 13:43:09 +0000 (Thu, 29 Jul 2010) Log Message: ----------- [Fix] The panic button could lead to crashes with some plugins like Superwave P8 (tx Rakib) [Ref] Small changes here and there. [Mod] OpenMPT: Version is now 1.18.02.07 Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/Sndmix.cpp Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2010-07-28 23:19:58 UTC (rev 664) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2010-07-29 13:43:09 UTC (rev 665) @@ -503,7 +503,7 @@ DefineKeyCommand(kcPrevDocument, 1693, kcVisible, kcNoDummy, _T("Previous Document")); DefineKeyCommand(kcNextDocument, 1694, kcVisible, kcNoDummy, _T("Next Document")); //time saving HACK: - for(size_t j = kcVSTGUIStartNotes; j <= kcVSTGUINoteStopA_3; j++) + for(size_t j = kcVSTGUIStartNotes; j <= kcVSTGUIEndNoteStops; j++) { DefineKeyCommand((CommandID)j, 1695 + j - kcVSTGUIStartNotes, kcHidden, kcNoDummy, _T("Auto Note in some context")); } Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2010-07-28 23:19:58 UTC (rev 664) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2010-07-29 13:43:09 UTC (rev 665) @@ -2709,8 +2709,10 @@ // Panic button. At the moment, it just resets all VSTi and sample notes. if(m_pModPlaying && m_pModPlaying->GetSoundFile()) { + BEGIN_CRITICAL(); + m_pModPlaying->GetSoundFile()->ResetChannels(); m_pModPlaying->GetSoundFile()->StopAllVsti(); - m_pModPlaying->GetSoundFile()->ResetChannels(); + END_CRITICAL(); } } Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-28 23:19:58 UTC (rev 664) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-29 13:43:09 UTC (rev 665) @@ -335,7 +335,7 @@ if(m_SndFile.m_nRestartPos > 0 && !CSoundFile::GetModSpecifications(nNewType).hasRestartPos) { m_SndFile.m_nRestartPos = 0; - AddToLog("WARNING: Restart position is not support by the new format.\n"); + AddToLog("WARNING: Restart position is not supported by the new format.\n"); } Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-07-28 23:19:58 UTC (rev 664) +++ trunk/OpenMPT/mptrack/version.h 2010-07-29 13:43:09 UTC (rev 665) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 #define VER_MINOR 02 -#define VER_MINORMINOR 06 +#define VER_MINORMINOR 07 //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/Sndmix.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndmix.cpp 2010-07-28 23:19:58 UTC (rev 664) +++ trunk/OpenMPT/soundlib/Sndmix.cpp 2010-07-29 13:43:09 UTC (rev 665) @@ -883,14 +883,15 @@ // Master Volume + Pre-Amplification / Attenuation setup DWORD nMasterVol; { - int nchn32 = 0; + /*int nchn32 = 0; MODCHANNEL *pChn = Chn; for (UINT nChn=0; nChn<m_nChannels; nChn++,pChn++) { //if(!(pChn->dwFlags & CHN_MUTE)) //removed by rewbs: fix http://www.modplug.com/forum/viewtopic.php?t=3358 nchn32++; } - nchn32 = CLAMP(nchn32, 1, 31); + nchn32 = CLAMP(nchn32, 1, 31);*/ + int nchn32 = CLAMP(m_nChannels, 1, 31); DWORD mastervol; @@ -970,8 +971,7 @@ else { pChn->nPan += pChn->nPanSwing; - if(pChn->nPan > 256) pChn->nPan = 256; - if(pChn->nPan < 0) pChn->nPan = 0; + pChn->nPan = CLAMP(pChn->nPan, 0, 256); pChn->nPanSwing = 0; pChn->nRealPan = pChn->nPan; } @@ -1009,7 +1009,7 @@ if (pChn->dwFlags & CHN_TREMOLO) { UINT trempos = pChn->nTremoloPos; - // IT compatibility: Why would want to not execute tremolo at volume 0? + // IT compatibility: Why would you not want to execute tremolo at volume 0? if (vol > 0 || IsCompatibleMode(TRK_IMPULSETRACKER)) { // IT compatibility: We don't need a different attenuation here because of the different tables we're going to use @@ -1103,18 +1103,18 @@ // and release envelope beginning. if (pIns->VolEnv.nReleaseNode != ENV_RELEASE_NODE_UNSET && pChn->nVolEnvPosition>=pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode] - && pChn->nVolEnvValueAtReleaseJump != NOT_YET_RELEASED) { + && pChn->nVolEnvValueAtReleaseJump != NOT_YET_RELEASED) + { int envValueAtReleaseJump = pChn->nVolEnvValueAtReleaseJump; int envValueAtReleaseNode = pIns->VolEnv.Values[pIns->VolEnv.nReleaseNode] << 2; //If we have just hit the release node, force the current env value //to be that of the release node. This works around the case where // we have another node at the same position as the release node. - if (pChn->nVolEnvPosition==pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode]) { - envvol=envValueAtReleaseNode; - } + if (pChn->nVolEnvPosition == pIns->VolEnv.Ticks[pIns->VolEnv.nReleaseNode]) + envvol = envValueAtReleaseNode; - int relativeVolumeChange = (envvol-envValueAtReleaseNode)*2; + int relativeVolumeChange = (envvol - envValueAtReleaseNode) * 2; envvol = envValueAtReleaseJump + relativeVolumeChange; } vol = (vol * CLAMP(envvol, 0, 512)) >> 8; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-08-01 14:18:32
|
Revision: 666 http://modplug.svn.sourceforge.net/modplug/?rev=666&view=rev Author: saga-games Date: 2010-08-01 14:18:25 +0000 (Sun, 01 Aug 2010) Log Message: ----------- [Fix] Colour Setup: Some colours in the MPT default colour scheme were not set up properly when switching between presets. [Imp] Instrument Editor: When pasting an envelope with a release node, it's now ignored in formats that don't support it. [Imp] Sample Editor: Reduced change of a conflict when using the shift key while drawing samples. [Mod] Invert loop (.MOD effect) is now ignored on 16-bit samples (only important during editing, since .MODs can only contain 8-bit samples anyway) [Mod] In the mod type dialog, the "misc flags" can now be toggled using check buttons instead of an edit field. Should be a lot more intuitive. [Mod] Updated panic button bitmap. [Mod] Updated history.txt [Mod] OpenMPT: Version is now 1.18.03.00 (release version) Modified Paths: -------------- trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Moptions.cpp trunk/OpenMPT/mptrack/View_smp.cpp trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/res/MAINBAR.BMP trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/packageTemplate/OMPT_1.18_ReleaseNotes.html trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-08-01 14:18:25 UTC (rev 666) @@ -1609,7 +1609,8 @@ if(dwPos < dwMemSize) { BYTE r = static_cast<BYTE>(atoi(p + dwPos)); - if(r == 0 || r >= nPoints) r = ENV_RELEASE_NODE_UNSET; + if(r == 0 || r >= nPoints || !m_SndFile.GetModSpecifications().hasReleaseNode) + r = ENV_RELEASE_NODE_UNSET; pEnv->nReleaseNode = r; } } Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2010-08-01 14:18:25 UTC (rev 666) @@ -399,6 +399,7 @@ CustomColors[MODCOLOR_TEXTCURROW] = RGB(0x00, 0x00, 0x00); CustomColors[MODCOLOR_BACKSELECTED] = RGB(0x00, 0x00, 0x00); CustomColors[MODCOLOR_TEXTSELECTED] = RGB(0xFF, 0xFF, 0xFF); + CustomColors[MODCOLOR_SAMPLE] = RGB(0xFF, 0x00, 0x00); CustomColors[MODCOLOR_BACKPLAYCURSOR] = RGB(0xFF, 0xFF, 0x80); CustomColors[MODCOLOR_TEXTPLAYCURSOR] = RGB(0x00, 0x00, 0x00); CustomColors[MODCOLOR_BACKHILIGHT] = RGB(0xE0, 0xE8, 0xE0); @@ -408,6 +409,7 @@ CustomColors[MODCOLOR_PANNING] = RGB(0x00, 0x80, 0x80); CustomColors[MODCOLOR_PITCH] = RGB(0x80, 0x80, 0x00); CustomColors[MODCOLOR_GLOBALS] = RGB(0x80, 0x00, 0x00); + CustomColors[MODCOLOR_ENVELOPES] = RGB(0x00, 0x00, 0xFF); CustomColors[MODCOLOR_VUMETER_LO] = RGB(0x00, 0xC8, 0x00); CustomColors[MODCOLOR_VUMETER_MED] = RGB(0xFF, 0xC8, 0x00); CustomColors[MODCOLOR_VUMETER_HI] = RGB(0xE1, 0x00, 0x00); @@ -492,6 +494,7 @@ CustomColors[MODCOLOR_TEXTCURROW] = RGB(0x00, 0x00, 0x00); CustomColors[MODCOLOR_BACKSELECTED] = RGB(0x00, 0x00, 0x00); CustomColors[MODCOLOR_TEXTSELECTED] = RGB(0xDD, 0xD7, 0xCC); + CustomColors[MODCOLOR_SAMPLE] = RGB(0x00, 0xFF, 0x00); CustomColors[MODCOLOR_BACKPLAYCURSOR] = RGB(0xA9, 0x99, 0x7A); CustomColors[MODCOLOR_TEXTPLAYCURSOR] = RGB(0x00, 0x00, 0x00); CustomColors[MODCOLOR_BACKHILIGHT] = RGB(0xCE, 0xC5, 0xB5); @@ -501,7 +504,6 @@ CustomColors[MODCOLOR_PANNING] = RGB(0x00, 0x68, 0x68); CustomColors[MODCOLOR_PITCH] = RGB(0x62, 0x62, 0x00); CustomColors[MODCOLOR_GLOBALS] = RGB(0x66, 0x00, 0x00); - CustomColors[MODCOLOR_SAMPLE] = RGB(0x00, 0xFF, 0x00); CustomColors[MODCOLOR_ENVELOPES] = RGB(0xFF, 0x00, 0x00); CustomColors[MODCOLOR_VUMETER_LO] = RGB(0x00, 0xC8, 0x00); CustomColors[MODCOLOR_VUMETER_MED] = RGB(0xFF, 0xC8, 0x00); Modified: trunk/OpenMPT/mptrack/View_smp.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_smp.cpp 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/View_smp.cpp 2010-08-01 14:18:25 UTC (rev 666) @@ -1361,7 +1361,7 @@ bool oldsel = (m_dwBeginSel != m_dwEndSel) ? true : false; // shift + click = update selection - if(CMainFrame::GetInputHandler()->ShiftPressed()) + if(!m_bDrawingEnabled && CMainFrame::GetInputHandler()->ShiftPressed()) { oldsel = true; m_dwEndDrag = ScreenToSample(point.x); Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2010-08-01 14:18:25 UTC (rev 666) @@ -131,9 +131,8 @@ // -> CODE#0023 // -> DESC="IT project files (.itp)" DDX_Control(pDX, IDC_CHECK6, m_CheckBox6); - DDX_Control(pDX, IDC_CHECK_PT1X, m_CheckBoxPT1x); - DDX_Control(pDX, IDC_EDIT_FLAGS, m_EditFlag); // -! NEW_FEATURE#0023 + DDX_Control(pDX, IDC_CHECK_PT1X, m_CheckBoxPT1x); //}}AFX_DATA_MAP } @@ -203,8 +202,6 @@ SetDlgItemText(IDC_EDIT_CREATEDWITH, MptVersion::ToStr(m_pSndFile->m_dwCreatedWithVersion)); SetDlgItemText(IDC_EDIT_SAVEDWITH, MptVersion::ToStr(m_pSndFile->m_dwLastSavedWithVersion)); - m_EditFlag.SetLimitText(16); - UpdateDialog(); EnableToolTips(TRUE); @@ -273,39 +270,24 @@ const bool XMorITorMPT = ((m_TypeBox.GetItemData(m_TypeBox.GetCurSel()) & (MOD_TYPE_XM | MOD_TYPE_IT | MOD_TYPE_MPT)) != 0); const bool ITorMPT = ((m_TypeBox.GetItemData(m_TypeBox.GetCurSel()) & (MOD_TYPE_IT | MOD_TYPE_MPT)) != 0); - const bool XM = m_TypeBox.GetItemData(m_TypeBox.GetCurSel()) == MOD_TYPE_XM; - // Misc Flags box - CWnd* p = GetDlgItem(IDC_EDIT_FLAGS); - if(p) p->ShowWindow(XMorITorMPT); - p = GetDlgItem(IDC_FLAG_EXPLANATIONS); - if(p) + // Misc Flags + if(ITorMPT) { - p->ShowWindow(XMorITorMPT); - if(ITorMPT) - p->SetWindowText("1. Enable more IT compatible playback.\n" - "2. Use old random variation behavior for instruments.\n" - "3. Enable plugin volume command bug emulation."); - else if(XM) p->SetWindowText("1. Enable more FT2 compatible playback.\n" - "2. Unused\n" - "3. Plugin volume command bug"); - } - - GetDlgItem(IDC_FLAGEDITTITLE)->ShowWindow(XMorITorMPT); - GetDlgItem(IDC_FRAME_MPTEXT)->ShowWindow(XMorITorMPT); - if(XMorITorMPT) + GetDlgItem(IDC_CHK_COMPATPLAY)->SetWindowText(_T("More Impulse Tracker compatible playback")); + } else { - char str[17] = "0000000000000000"; - const uint16 f = m_pSndFile->GetModFlags(); - BYTE lastTrue = 0, i; - for(i = 0; i<16; i++) - { - if((f & (1 << i)) != 0) {str[i] = '1'; lastTrue = i;} - } - str[max(3, lastTrue+1)] = 0; - SetDlgItemText(IDC_EDIT_FLAGS, str); + GetDlgItem(IDC_CHK_COMPATPLAY)->SetWindowText(_T("More Fasttracker 2 compatible playback")); } + GetDlgItem(IDC_CHK_COMPATPLAY)->ShowWindow(XMorITorMPT); + GetDlgItem(IDC_CHK_MIDICCBUG)->ShowWindow(XMorITorMPT); + GetDlgItem(IDC_CHK_OLDRANDOM)->ShowWindow(ITorMPT); + + CheckDlgButton(IDC_CHK_COMPATPLAY, m_pSndFile->GetModFlag(MSF_COMPATIBLE_PLAY)); + CheckDlgButton(IDC_CHK_MIDICCBUG, m_pSndFile->GetModFlag(MSF_MIDICC_BUGEMULATION)); + CheckDlgButton(IDC_CHK_OLDRANDOM, m_pSndFile->GetModFlag(MSF_OLDVOLSWING)); + // Mixmode Box GetDlgItem(IDC_TEXT_MIXMODE)->ShowWindow(XMorITorMPT); m_PlugMixBox.ShowWindow(XMorITorMPT); @@ -485,14 +467,10 @@ if(m_nType & (MOD_TYPE_IT | MOD_TYPE_MPT | MOD_TYPE_XM)) { - uint16 val = 0; - char str[18]; memset(str, 0, 18); - GetDlgItemText(IDC_EDIT_FLAGS, str, 17); - for(size_t i = 0; i<strlen(str); i++) - { - if(str[i] != '0') val |= (1 << i); - } - m_pSndFile->SetModFlags(val); + m_pSndFile->SetModFlags(0); + if(IsDlgButtonChecked(IDC_CHK_COMPATPLAY)) m_pSndFile->SetModFlag(MSF_COMPATIBLE_PLAY, true); + if(IsDlgButtonChecked(IDC_CHK_MIDICCBUG)) m_pSndFile->SetModFlag(MSF_MIDICC_BUGEMULATION, true); + if(IsDlgButtonChecked(IDC_CHK_OLDRANDOM)) m_pSndFile->SetModFlag(MSF_OLDVOLSWING, true); } m_pSndFile->m_nRowsPerBeat = GetDlgItemInt(IDC_ROWSPERBEAT); @@ -557,6 +535,15 @@ case IDC_COMBO_MIXLEVELS: strTipText = "Mixing method of sample and VST levels."; break; + case IDC_CHK_COMPATPLAY: + strTipText = "Play commands as the original tracker would play them (recommended)"; + break; + case IDC_CHK_MIDICCBUG: + strTipText = "Emulate an old bug which sent wrong volume messages to VSTis (not recommended)"; + break; + case IDC_CHK_OLDRANDOM: + strTipText = "Use old (buggy) random volume / panning variation algorithm (not recommended)"; + break; } if (pNMHDR->code == TTN_NEEDTEXTA) Modified: trunk/OpenMPT/mptrack/dlg_misc.h =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.h 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/dlg_misc.h 2010-08-01 14:18:25 UTC (rev 666) @@ -12,7 +12,6 @@ public: CComboBox m_TypeBox, m_ChannelsBox, m_TempoModeBox, m_PlugMixBox; CButton m_CheckBox1, m_CheckBox2, m_CheckBox3, m_CheckBox4, m_CheckBox5, m_CheckBoxPT1x; - CEdit m_EditFlag; CSoundFile *m_pSndFile; UINT m_nChannels; MODTYPE m_nType; @@ -23,8 +22,6 @@ CButton m_CheckBox6; // -! NEW_FEATURE#0023 - CButton m_CheckBoxITCompatiblePlay; - public: CModTypeDlg(CSoundFile *pSndFile, CWnd *parent):CDialog(IDD_MODDOC_MODTYPE, parent) { m_pSndFile = pSndFile; m_nType = MOD_TYPE_NONE; m_nChannels = 0; } bool VerifyData(); Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/mptrack.rc 2010-08-01 14:18:25 UTC (rev 666) @@ -612,7 +612,7 @@ END IDD_CONTROL_INSTRUMENTS DIALOGEX 0, 0, 558, 173 -STYLE DS_SETFONT | WS_CHILD +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN EDITTEXT IDC_EDIT_INSTRUMENT,87,7,29,12,ES_AUTOHSCROLL | ES_NUMBER @@ -694,7 +694,7 @@ GROUPBOX "Tuning (experimental)",IDC_STATIC,364,28,92,28 END -IDD_MODDOC_MODTYPE DIALOGEX 0, 0, 262, 317 +IDD_MODDOC_MODTYPE DIALOGEX 0, 0, 262, 311 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Song Properties" FONT 8, "MS Shell Dlg", 0, 0, 0x0 @@ -703,33 +703,35 @@ PUSHBUTTON "Cancel",IDCANCEL,204,24,50,14 COMBOBOX IDC_COMBO1,12,18,108,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP COMBOBOX IDC_COMBO2,126,18,66,77,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - CONTROL "Embed instrument parameters in ITP",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,36,174,8 - CONTROL "Linear Frequency Slides",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,72,91,10 - CONTROL "Old Effects (IT)",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,72,66,10 - CONTROL "Fast Volume Slides (S3M)",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,84,96,10 - CONTROL "Compatible Gxx (IT)",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,84,84,10 - CONTROL "Extended filter range",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,96,81,10 - CONTROL "ProTracker 1.x Mode (MOD)",IDC_CHECK_PT1X,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,96,108,10 - RTEXT "Mix Levels:",IDC_TEXT_MIXMODE,18,134,81,8 - COMBOBOX IDC_COMBO_MIXLEVELS,108,132,84,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - RTEXT "Miscellaneous flags(0/1):",IDC_FLAGEDITTITLE,18,150,81,12,SS_CENTERIMAGE - EDITTEXT IDC_EDIT_FLAGS,108,150,84,12,ES_AUTOHSCROLL - COMBOBOX IDC_COMBO_TEMPOMODE,36,222,108,77,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - EDITTEXT IDC_ROWSPERBEAT,156,222,24,12,ES_AUTOHSCROLL | ES_NUMBER - EDITTEXT IDC_ROWSPERMEASURE,156,240,24,12,ES_AUTOHSCROLL | ES_NUMBER - EDITTEXT IDC_EDIT_CREATEDWITH,78,276,166,13,ES_AUTOHSCROLL | ES_READONLY,WS_EX_STATICEDGE - EDITTEXT IDC_EDIT_SAVEDWITH,78,294,166,13,ES_AUTOHSCROLL | ES_READONLY,WS_EX_STATICEDGE + CONTROL "&Embed instrument parameters in ITP",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,36,174,8 + CONTROL "&Linear Frequency Slides",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,72,91,10 + CONTROL "&Old Effects (IT)",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,72,66,10 + CONTROL "Fast &Volume Slides (S3M)",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,84,96,10 + CONTROL "Compatible &Gxx (IT)",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,84,84,10 + CONTROL "Extended &filter range",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,96,81,10 + CONTROL "&ProTracker 1.x Mode (MOD)",IDC_CHECK_PT1X,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,120,96,108,10 + LTEXT "Mix Levels:",IDC_TEXT_MIXMODE,18,134,42,8 + COMBOBOX IDC_COMBO_MIXLEVELS,60,132,84,51,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "More &compatible playback",IDC_CHK_COMPATPLAY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,150,222,12 + CONTROL "Plugin volume command &bug emulation",IDC_CHK_MIDICCBUG, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,162,222,12 + CONTROL "Old &random variation behaviour for instruments",IDC_CHK_OLDRANDOM, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,174,222,12 + COMBOBOX IDC_COMBO_TEMPOMODE,36,217,108,77,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_ROWSPERBEAT,156,217,24,12,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_ROWSPERMEASURE,156,234,24,12,ES_AUTOHSCROLL | ES_NUMBER + EDITTEXT IDC_EDIT_CREATEDWITH,78,271,166,13,ES_AUTOHSCROLL | ES_READONLY,WS_EX_STATICEDGE + EDITTEXT IDC_EDIT_SAVEDWITH,78,289,166,13,ES_AUTOHSCROLL | ES_READONLY,WS_EX_STATICEDGE GROUPBOX "Type",IDC_FRAME_MODTYPE,6,6,192,48 GROUPBOX "Playback",IDC_FRAME_MODFLAGS,6,60,246,54 - GROUPBOX "Extended Playback Options (OpenMPT only)",IDC_FRAME_MPTEXT,6,120,246,84 - LTEXT "",IDC_FLAG_EXPLANATIONS,18,168,222,26 - GROUPBOX "Tempo",IDC_FRAME_TEMPOMODE,6,210,246,48 - LTEXT "Mode:",IDC_TEXT_TEMPOMODE,12,224,21,8 - LTEXT "Rows/beat",IDC_TEXT_ROWSPERBEAT,186,224,36,8 - LTEXT "Rows/measure",IDC_TEXT_ROWSPERMEASURE,186,242,49,8 - GROUPBOX "OpenMPT Version Info",IDC_FRAME_MPTVERSION,6,263,246,48 - RTEXT "IDC_TEXT_CREATEDWITH",IDC_TEXT_CREATEDWITH,18,278,54,8 - RTEXT "IDC_TEXT_SAVEDWITH",IDC_TEXT_SAVEDWITH,18,295,54,8 + GROUPBOX "Extended Playback Options (OpenMPT only)",IDC_FRAME_MPTEXT,6,120,246,78 + GROUPBOX "Tempo",IDC_FRAME_TEMPOMODE,6,204,246,48 + LTEXT "Mode:",IDC_TEXT_TEMPOMODE,12,218,21,8 + LTEXT "Rows/beat",IDC_TEXT_ROWSPERBEAT,186,218,36,8 + LTEXT "Rows/measure",IDC_TEXT_ROWSPERMEASURE,186,236,49,8 + GROUPBOX "OpenMPT Version Info",IDC_FRAME_MPTVERSION,6,257,246,48 + RTEXT "IDC_TEXT_CREATEDWITH",IDC_TEXT_CREATEDWITH,18,273,54,8 + RTEXT "IDC_TEXT_SAVEDWITH",IDC_TEXT_SAVEDWITH,18,289,54,8 END IDD_SHOWLOG DIALOG 0, 0, 300, 106 @@ -807,7 +809,7 @@ PUSHBUTTON "Clone...",IDC_CLONEPLUG,103,207,34,13,NOT WS_VISIBLE,WS_EX_STATICEDGE PUSHBUTTON "<<",IDC_BUTTON5,11,191,18,13,NOT WS_TABSTOP,WS_EX_STATICEDGE PUSHBUTTON ">>",IDC_BUTTON4,32,191,18,13,NOT WS_TABSTOP,WS_EX_STATICEDGE - EDITTEXT IDC_EDIT13,310,191,96,13,ES_CENTER | ES_AUTOHSCROLL + EDITTEXT IDC_EDIT13,312,191,94,13,ES_CENTER | ES_AUTOHSCROLL COMBOBOX IDC_COMBO8,16,239,102,68,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Load",IDC_BUTTON6,122,239,27,13,0,WS_EX_STATICEDGE PUSHBUTTON "Save",IDC_BUTTON8,154,239,27,13,0,WS_EX_STATICEDGE @@ -820,6 +822,7 @@ CONTROL "Expand",IDC_CHECK12,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,199,271,37,10 CONTROL "Dry mix",IDC_CHECK11,"Button",BS_AUTOCHECKBOX | BS_FLAT | WS_TABSTOP,199,286,37,10 COMBOBOX IDC_COMBO9,285,241,62,99,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Gain: x 1.0",IDC_STATIC2,353,241,37,14,SS_CENTERIMAGE CONTROL "",IDC_SPIN10,"msctls_updown32",UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS,392,242,9,11 COMBOBOX IDC_COMBO7,285,261,117,68,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "",IDC_SLIDER10,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,314,282,88,14,WS_EX_STATICEDGE @@ -841,16 +844,15 @@ LTEXT "Effect:",IDC_STATIC,216,146,29,8 LTEXT "Effect:",IDC_STATIC,319,146,29,8 CTEXT "Display name",IDC_STATIC,263,191,48,13,SS_CENTERIMAGE,WS_EX_STATICEDGE + CTEXT "I/O Type:",IDC_STATIC,263,208,47,13,SS_CENTERIMAGE,WS_EX_STATICEDGE + CONTROL "",IDC_TEXT6,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | WS_GROUP,312,208,95,13,WS_EX_STATICEDGE + GROUPBOX "Factory preset",IDC_STATIC,11,226,177,34 CTEXT "Parameter",IDC_STATIC,16,266,43,13,SS_CENTERIMAGE,WS_EX_STATICEDGE + GROUPBOX "",IDC_STATIC,11,255,177,49 + GROUPBOX "Mix settings",IDC_STATIC,193,226,214,78 + CTEXT "Mix mode",IDC_STATIC,245,241,37,13,SS_CENTERIMAGE,WS_EX_STATICEDGE CTEXT "Output to",IDC_STATIC,245,261,37,13,SS_CENTERIMAGE,WS_EX_STATICEDGE - CONTROL "",IDC_TEXT6,"Static",SS_LEFTNOWORDWRAP | SS_CENTERIMAGE | WS_GROUP,311,208,96,13,WS_EX_STATICEDGE CTEXT "Wet Dry Ratio",IDC_STATIC8,245,282,65,14,SS_CENTERIMAGE,WS_EX_STATICEDGE - CTEXT "Mix mode",IDC_STATIC,245,241,37,13,SS_CENTERIMAGE,WS_EX_STATICEDGE - LTEXT "Gain: x 1.0",IDC_STATIC2,353,241,34,14,SS_CENTERIMAGE - GROUPBOX "Mix settings",IDC_STATIC,193,226,214,78 - GROUPBOX "Factory preset",IDC_STATIC,11,226,177,34 - GROUPBOX "",IDC_STATIC,11,255,177,49 - CTEXT "I/O Type:",IDC_STATIC,263,208,47,13,SS_CENTERIMAGE,WS_EX_STATICEDGE END IDD_EDIT_FIND DIALOGEX 0, 0, 182, 145 @@ -1246,18 +1248,18 @@ RTEXT "--",IDC_TEXT2,260,89,22,8 END -IDD_SELECTMIXPLUGIN DIALOGEX 0, 0, 243, 220 -STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME +IDD_SELECTMIXPLUGIN DIALOGEX 0, 0, 249, 220 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "Mix Plugins" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN - LTEXT "Filter:",IDC_STATIC_VSTNAMEFILTER,8,9,18,8 - EDITTEXT IDC_NAMEFILTER,28,7,152,14,ES_AUTOHSCROLL + LTEXT "Filter:",IDC_STATIC_VSTNAMEFILTER,6,9,18,8 + EDITTEXT IDC_NAMEFILTER,30,6,150,14,ES_AUTOHSCROLL CONTROL "Tree1",IDC_TREE1,"SysTreeView32",TVS_DISABLEDRAGDROP | TVS_SHOWSELALWAYS | WS_HSCROLL | WS_TABSTOP,6,24,174,180,WS_EX_CLIENTEDGE - DEFPUSHBUTTON "Add to Song",IDOK,187,6,50,14 - PUSHBUTTON "New plugin...",IDC_BUTTON1,188,23,50,14,BS_MULTILINE - PUSHBUTTON "Remove",IDC_BUTTON2,188,40,50,14 - PUSHBUTTON "Cancel",IDCANCEL,186,189,50,14 + DEFPUSHBUTTON "Add to Song",IDOK,187,6,53,14 + PUSHBUTTON "New plugin...",IDC_BUTTON1,188,23,52,14,BS_MULTILINE + PUSHBUTTON "Remove",IDC_BUTTON2,188,40,52,14 + PUSHBUTTON "Cancel",IDCANCEL,186,189,54,14 LTEXT "IDC_TEXT_CURRENT_VSTPLUG",IDC_TEXT_CURRENT_VSTPLUG,6,208,234,8 END @@ -1594,7 +1596,7 @@ IDD_MODDOC_MODTYPE, DIALOG BEGIN RIGHTMARGIN, 248 - BOTTOMMARGIN, 310 + BOTTOMMARGIN, 304 END IDD_SHOWLOG, DIALOG @@ -1707,7 +1709,7 @@ IDD_SELECTMIXPLUGIN, DIALOG BEGIN LEFTMARGIN, 7 - RIGHTMARGIN, 236 + RIGHTMARGIN, 242 TOPMARGIN, 7 BOTTOMMARGIN, 213 END Modified: trunk/OpenMPT/mptrack/res/MAINBAR.BMP =================================================================== (Binary files differ) Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/resource.h 2010-08-01 14:18:25 UTC (rev 666) @@ -841,9 +841,9 @@ #define IDC_BUTTON_REMOVE 2318 #define IDC_CHECK_MIDILEARN 2319 #define IDC_MIDIPLAYCONTROL 2320 -#define IDC_FLAG_EXPLANATIONS 2321 -#define IDC_FLAGEDITTITLE 2322 -#define IDC_EDIT_FLAGS 2323 +#define IDC_CHK_COMPATPLAY 2321 +#define IDC_CHK_MIDICCBUG 2322 +#define IDC_CHK_OLDRANDOM 2323 #define IDC_CHECKCAPTURE 2324 #define IDC_SPINMOVEMAPPING 2325 #define IDC_BUTTON_HALF 2326 @@ -1208,7 +1208,7 @@ #define ID_PATTERN_EDIT_PCNOTE_PLUGIN 60448 #define ID_ENVELOPE_ZOOM_IN 60449 #define ID_ENVELOPE_ZOOM_OUT 60450 -#define ID_PANIC 60451 +#define ID_PANIC 60451 // Next default values for new objects // Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/mptrack/version.h 2010-08-01 14:18:25 UTC (rev 666) @@ -14,8 +14,8 @@ //Version definitions. The only thing that needs to be changed when changing version number. #define VER_MAJORMAJOR 1 #define VER_MAJOR 18 -#define VER_MINOR 02 -#define VER_MINORMINOR 07 +#define VER_MINOR 03 +#define VER_MINORMINOR 00 //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/packageTemplate/History.txt =================================================================== --- trunk/OpenMPT/packageTemplate/History.txt 2010-07-29 13:43:09 UTC (rev 665) +++ trunk/OpenMPT/packageTemplate/History.txt 2010-08-01 14:18:25 UTC (rev 666) @@ -10,211 +10,298 @@ (tx XYZ): thanks to XYZ for telling us about the bug +v1.18.03.00 (August 2010, revision 666) +--------------------------------------- +General tab + [Imp] <Jojo> To prevent OpenMPT from hanging while switching between plugins (or switching to the general tab), the preset box is only filled when it gets the focus. This makes working with Synth1 a lot easier, since it has an insane amount of presets... :) + [Mod] <Jojo> Changed tab order of the lower panel (now it's more logical to me) + +Sequence editor + [Imp] <Jojo> When inserting patterns at an empty position, the position counter is not increased anymore. + [Imp] <Jojo> Improved sequence name display in context menu for empty sequences. + +Pattern tab::pattern editing + [Imp] <Jojo> Just like in MPT 1.16, it is now possible again to interpolate between an effect and "nothing". In that case, the same value as the already existing one is repeated between the two rows. + [Fix] <Jojo> When the first column of a pattern selection (larger than one selection field) was the parameter column, PCNote values in this column were not reset properly. + [Fix] <Jojo> Pattern Editor: Transposing notes up/down doesn't allow notes which are actually supported by the current module format (f.e. notes below C-1 in XMs) anymore. + [Fix] <Jojo> Keyboard shortcut for toggling record state didn't save the change, so it was reset with every new module. + +Pattern tab::Note properties + [Imp] <Jojo> Effect info now shows the real finetune values for E5x in MOD/XM and E2x in S3M instead of just 0...15. + [Imp] <Jojo> Set envelope position effect (Lxx in XM) is now explained better. + [Fix] <Jojo> Fixed a null pointer related crash when accessing the note properties of malicious and not-so-malicious modules (f.e. jt_pools.xm) which have more than 256 sample slots. + +Sample tab + [New] <Jojo> It's now also possible to create sample selections using Shift + click (this is still behaving a bit non-obvious if you don't know what you're doing :). + [New] <Jojo> Sample Drawing: Horizontal lines can now be drawn by holding down the shift key. + [Imp] <Jojo> Finetune range is now limited from -8 to 7 for MOD files. + [Imp] <Jojo> When hovering the relative note and finetune controls, the actual C-5 frequency is now also shown for MOD files. Previously, this only worked for XM files. + [Fix] <Jojo> When using the spin button next to the finetune or frequency control, the module was not marked as modified. + +Instrument tab + [New] <Jojo> Pressing Ctrl while dragging a point in the envelope editor now also moves the tail of the envelope. + [Imp] <Jojo> More helpful value display for the panning envelope in the status bar with indication what's left and what's right. + [Imp] <Jojo> If an instrument is not initialized yet, this is done automatically now, so that changes done to the instrument are not lost, although it looks like they are actually applied (f.e. when trying to edit a previously deleted instrument). + [Imp] <Jojo> Fadeout values up to 32767 are allowed again for XM files, as FT2 can actually handle them (and other apps like Milky support them as well) + [Imp] <Jojo> Panning ranges from 0 to 256 again for MPTM, and from 0 to 64 for IT files (previously, it ranged from 0 to 255). + [Imp] <Jojo> Sample Map accepts various new shortcuts now. + [Imp] <Jojo> When pasting an envelope with a release node, it's now ignored in formats that don't support it. + [Reg] <Jojo> Envelope release nodes cannot be enabled for IT files anymore, but they are still played for compatibility. (One has to start removing the crap from the old formats at some point...) + +Treeview + [Imp] <Jojo> Treeview: Ask for confirmation when deleting patterns, samples, instruments, sequences. + [Fix] <Jojo> Deleting a sample from the treeview and then applying undo for this sample in the sample editor crashed OpenMPT. + +Mod conversion + [Imp] <Jojo> Some improvements with converting note cuts, ECx/SCx and EDx/SDx. + [Imp] <Jojo> When converting to XM, rogue note delays are removed from the patterns to avoid interference with a FT2 bug. + [Imp] <Jojo> Envelope release nodes are now removed when converting from MPTM. + [Fix] <Jojo> When converting to MPTM, "+++" separator patterns are not recognized as sub tune indicators anymore, as that was quite annoying. + [Fix] <Jojo> Channel settings were not reset properly for MOD/XM/S3M, only the first channel was fixed. (tx Sam_Zen) + [Fix] <Jojo> Extra fine portamento was not converted properly when converting from IT/MPTM/S3M to XM. + +Playback (see also format-specific changes below) + [Mod] <Jojo> Invert loop (.MOD effect) is now ignored on 16-bit samples (only important during editing, since .MODs can only contain 8-bit samples anyway) + [Fix] <Jojo> The Pattern Loop command did not work properly on rows > 255 + +IT::Saving + [Imp] <Jojo> If a plugin is specified for an IT instrument and no MIDI channel is assigned, the plugin is written into the IT instrument header (in MPT 1.16's old manner), so that MPT 1.16 / XMPlay / BASS can make us of "FX Send" again. (tx Skaven) + [Imp] <Jojo> If filter envelopes are used, a different value for the cmwt ("compatible with") field is now used in compatibility export (like in SchismTracker). + [Fix] <Jojo> Instrument panning was not converted properly. + +XM + [Fix] <Jojo> 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. + [Fix] <Jojo> Prevent notes to be stopped after a fadeout. This way, a portamento effect can pick up a faded instrument which is long enough. This occours for example in the bassline (channel 11) of jt_burn.xm. Not tested with many XMs yet, I hope this won't break anything else... + +XM::Saving + [Imp] <Jojo> Panbrello is not saved anymore in compatibility mode. + [Fix] <Jojo> Completely empty patterns are loaded as empty 64-row patterns in FT2, regardless of their original size. This is now being circumvented by adding a D00 effect at the end of such patterns. + [Fix] <Jojo> Saving XM files with 127 channels (sigh) was broken. + +S3M + [Fix] <Jojo> Samples with very short loops (4 bytes) are now loaded properly. Fixes "a tiny problem.s3m" by \slash. + [Fix] <Jojo> Notes with an SD0 effect were not ignored properly when there was a row delay effect on the same row. Now they should be ignored in any case. + +Other modules + [Imp] <Jojo> Song messages are now loaded with more accuracy for some formats. + [Imp] <Jojo> J2B Loader: J2B files with extended instrument settings and multiple samples per instrument work properly now. Such J2B files were not used in the game but have been created by JJ2 players using MOD2J2B. + [Imp] <Jojo> OKT Loader: Completely new IFF-based loader, translated from SchismTracker code with permission from Storlek. This loader is a *lot* more accurate, but still misses a few pattern effects. + [Imp] <Jojo> PSM Loader: Small improvements. + [Fix] <Jojo> MTM Loader: The "beats per track" (means lines per pattern) setting is now taken into account. + [Fix] <Jojo> PSM16 Loader: Since the control channels were muted, tempo commands were ignored, effectively slowing down some PSM16 tracks. + +Misc + [New] <Jojo> Experimental "panic" button on the main toolbar. At the moment, it just kills all VSTi and sample voices. + [Imp] <Jojo> Added mnemonic codes to the wave export controls. + [Mod] <Jojo> In the mod type dialog, the "misc flags" can now be toggled using check buttons instead of an edit field. + [Mod] <Jojo> Various file loaders / savers: A new logging mechanism is used to display only one message box with errors and warnings instead of many message boxes. + [Mod] <Jojo> Updated DE_jojo.mkb to include new shortcuts, remapped a few others (for IT-style). + [Fix] <Jojo> Colour Setup: Some colours in the MPT default colour scheme were not set up properly when switching between presets. + + v1.18.02.00 (May 2010, revision 610) ------------------------------------ +General tab + [Imp] <Jojo> Disabled tempo slider for MOD files (it was just confusing) + [Imp] <Jojo> Disabled global volume slider for MOD files, instead enabled the sample pre-amp slider (so it is also possible to make output louder) + [Imp] <Jojo> The "output to" dropdown list also shows the actual plugin name (instead of just the library name) now. + [Fix] <Jojo> Moving a plugin in MOD/S3M files doesn't mark them as modified anymore. The channel fx dropdown lists are now also disabled for those module types. + [Fix] <Jojo> The restart position edit control is disabled for S3M files. + [Fix] <coda> The background colour of the tabs in the channel configuration is now also correct when using WinXP Luna or Vista/Win7 Aero. -General tab - [Imp] <Jojo> Disabled tempo slider for MOD files (it was just confusing) - [Imp] <Jojo> Disabled global volume slider for MOD files, instead enabled the sample pre-amp slider (so it is also possible to make output louder) - [Imp] <Jojo> The "output to" dropdown list also shows the actual plugin name (instead of just the library name) now. - [Fix] <Jojo> Moving a plugin in MOD/S3M files doesn't mark them as modified anymore. The channel fx dropdown lists are now also disabled for those module types. - [Fix] <Jojo> The restart position edit control is disabled for S3M files. - [Fix] <coda> The background colour of the tabs in the channel configuration is now also correct when using WinXP Luna or Vista/Win7 Aero. - Sequence editor - [New] <Jojo> "Select All" shortcut also works here now. - [Imp] <Jojo> Sequence menu also allows to insert empty sequences now. - [Fix] <Jojo> Jumping between patterns also stops VSTi notes now. + [New] <Jojo> "Select All" shortcut also works here now. + [Imp] <Jojo> Sequence menu also allows to insert empty sequences now. + [Fix] <Jojo> Jumping between patterns also stops VSTi notes now. Pattern tab::pattern editing - [New] <Jojo> Extended context menu for PC Notes - [New] <Jojo> Key shortcut + context menu entry for toggling the plugin editor of the PC note that's under the cursor. - [Imp] <Jojo> Overflow paste now only uses one undo step. - [Imp] <Jojo> Instead of simply ignoring note off/cut/fade when working with .MOD files, it is converted to C00. - [Fix] <rewbs> Effect visualizer is now aware of PC notes (bug 3836). - [Fix] <Jojo> When using MIDI record or split keyboard settings, volume data was writting into the volume column in MOD format. - [Fix] <Jojo> When converting PC Notes to MIDI Macros, the instrument index is now also cleaned as well. Noticable for example when pasting PC notes into an IT module. - [Fix] <Jojo> Now, plugin slot 100 can also be automated using PC Notes. - [Fix] <Jojo> When pasting pattern data that exactly reached the pattern end with overflow paste enabled, a redundant undo point was created. - [Fix] <Jojo> Entered (volume) effects are now properly validated (makes a difference f.e. in MOD format where it was previously possible to enter effects like Hxx) - [Fix] <Jojo> Mix Paste: When in MPT behaviour mode, empty FX commands were not overwritten properly when there previously was an effect in that field but only the effect number (and not the param value) was reset. - [Fix] <Jojo> When deleting all patterns via the treeview and then switching to the pattern editor, pattern 0 is not created automatically anymore, to avoid confusion. - [Reg] <Jojo> Creating a selection using the Shift key + Mouse click now only works if there was previously no selection made; This seems reasonable as the old shift-behaviour seems to be widely used. - + [New] <Jojo> Extended context menu for PC Notes + [New] <Jojo> Key shortcut + context menu entry for toggling the plugin editor of the PC note that's under the cursor. + [Imp] <Jojo> Overflow paste now only uses one undo step. + [Imp] <Jojo> Instead of simply ignoring note off/cut/fade when working with .MOD files, it is converted to C00. + [Fix] <rewbs> Effect visualizer is now aware of PC notes (bug 3836). + [Fix] <Jojo> When using MIDI record or split keyboard settings, volume data was written into the volume column in MOD format. + [Fix] <Jojo> When converting PC Notes to MIDI Macros, the instrument index is now also cleaned as well. Noticeable for example when pasting PC notes into an IT module. + [Fix] <Jojo> Now, plugin slot 100 can also be automated using PC Notes. + [Fix] <Jojo> When pasting pattern data that exactly reached the pattern end with overflow paste enabled, a redundant undo point was created. + [Fix] <Jojo> Entered (volume) effects are now properly validated (makes a difference f.e. in MOD format where it was previously possible to enter effects like Hxx) + [Fix] <Jojo> Mix Paste: When in MPT behaviour mode, empty FX commands were not overwritten properly when there previously was an effect in that field but only the effect number (and not the param value) was reset. + [Fix] <Jojo> When deleting all patterns via the treeview and then switching to the pattern editor, pattern 0 is not created automatically anymore, to avoid confusion. + [Reg] <Jojo> Creating a selection using the Shift key + Mouse click now only works if there was previously no selection made; This seems reasonable as the old shift - behaviour seems to be widely used. + Pattern tab::GUI - [New] <Jojo> When the PT1x mode or the S3M "Amiga" flag are enabled, dodgy notes (i.e lower than C-4 or higher than B-6) are marked red. - [Imp] <Jojo> The status bar shows plugin and parameter names for PC notes now as well. - [Imp] <Jojo> Effect vis: Make use of song's own row highlighting variables instead of fixed global ones. - [Fix] <Jojo> The status bar ("Position x of y") only the showed order length for the first subtune if subtunes were separated by an "---" order item. - [Fix] <Jojo> Changing a channel plugin in MOD/S3M files doesn't mark them as modified anymore. - [Fix] <Jojo> When working with multiple sequences, switching to the pattern editor for the first time automatically marked the document as modified. + [New] <Jojo> When the PT1x mode or the S3M "Amiga" flag are enabled, dodgy notes (i.e lower than C-4 or higher than B-6) are marked red. + [Imp] <Jojo> The status bar shows plugin and parameter names for PC notes now as well. + [Imp] <Jojo> Effect vis: Make use of song's own row highlighting variables instead of fixed global ones. + [Fix] <Jojo> The status bar ("Position x of y") only the showed order length for the first sub tune if sub tunes were separated by an "---" order item. + [Fix] <Jojo> Changing a channel plugin in MOD/S3M files doesn't mark them as modified anymore. + [Fix] <Jojo> When working with multiple sequences, switching to the pattern editor for the first time automatically marked the document as modified. Pattern tab::Note properties - [Imp] <Jojo> Don't allow values > 63 for "break to row" commands in MOD/S3M. - [Imp] <Jojo> Since the behaviour of sliding commands with both nibbles set varies from tracker to tracker, "undefined" is always shown in the note properties in such cases. - [Fix] <Jojo> In the note properties, the Gxx effect for XM files was not limited properly. - [Fix] <Jojo> In Note Properties, the waveform display for S [345]x (and equivalent MOD/XM effeects) was not always fully visible ("continue" addition was cut off) - [Fix] <Jojo> Display "fine" / "extra fine" portamento effects properly (S3M/IT/MPTM), display SFx macro properly, display MOD effects with no memory properly. + [Imp] <Jojo> Don't allow values > 63 for "break to row" commands in MOD/S3M. + [Imp] <Jojo> Since the behaviour of sliding commands with both nibbles set varies from tracker to tracker, "undefined" is always shown in the note properties in such cases. + [Fix] <Jojo> In the note properties, the Gxx effect for XM files was not limited properly. + [Fix] <Jojo> In Note Properties, the waveform display for S [345]x (and equivalent MOD/XM effects) was not always fully visible ("continue" addition was cut off) + [Fix] <Jojo> Display "fine" / "extra fine" portamento effects properly (S3M/IT/MPTM), display SFx macro properly, display MOD effects with no memory properly. Pattern tab::Find/replace - [Fix] <Jojo> Find/Replace didn't work properly when replacing PC Notes with something that's not a PC Note. - [Fix] <Jojo> Instead of turning "Follow Song" off, the Find/Replace dialog toggled it. - + [Fix] <Jojo> Find/Replace didn't work properly when replacing PC Notes with something that's not a PC Note. + [Fix] <Jojo> Instead of turning "Follow Song" off, the Find/Replace dialog toggled it. + Sample tab - [New] <Jojo> Shift+New = Clone sample slot - [New] <Jojo> Option to not ask for RAW import settings again (settings are remembered independently for all modules) - [Imp] <Jojo> Remember previous settings in RAW import dialog - [Imp] <Jojo> When enabling (sustain) loop and no loop points are set yet, automatically set loop to full sample length or the currently selected part of the sample. - [Imp] <Jojo> Sample name and filename are now properly limited in length. - [Fix] <Jojo> When applying time stretch / pitch shift to an 8-bit sample and selecting the sample partly lead to partial upsampling, instead of upsampling the whole sample. - [Fix] <Jojo> Sample Undo: If no custom value was set, the default value was set ridiculously high (tx Paul Legovitch) - [Fix] <Jojo> Sample Undo: Fixed another possible problem when undoing actions with very little memory left. - [Fix] <Jojo> It was not possible to create the last sample slot (i.e. pressing "new sample" with a MOD file that had 30 samples would result in an error, although MOD supports 31 samples). - [Fix] <Jojo> When loading an extremely short raw file (f.e. 1 byte) twice, it crashed OpenMPT. - + [New] <Jojo> Shift+New = Clone sample slot + [New] <Jojo> Option to not ask for RAW import settings again (settings are remembered independently for all modules) + [Imp] <Jojo> Remember previous settings in RAW import dialog + [Imp] <Jojo> When enabling (sustain) loop and no loop points are set yet, automatically set loop to full sample length or the currently selected part of the sample. + [Imp] <Jojo> Sample name and filename are now properly limited in length. + [Fix] <Jojo> When applying time stretch / pitch shift to an 8-bit sample and selecting the sample partly lead to partial upsampling, instead of upsampling the whole sample. + [Fix] <Jojo> Sample Undo: If no custom value was set, the default value was set ridiculously high (tx Paul Legovitch) + [Fix] <Jojo> Sample Undo: Fixed another possible problem when undoing actions with very little memory left. + [Fix] <Jojo> It was not possible to create the last sample slot (i.e. pressing "new sample" with a MOD file that had 30 samples would result in an error, although MOD supports 31 samples). + [Fix] <Jojo> When loading an extremely short raw file (f.e. 1 byte) twice, it crashed OpenMPT. + Instrument tab - [New] <Jojo> Envelope zooming. Might still look very weird (especially the first tick and around loop points). Includes two new keyboard shortcuts. - [New] <Jojo> Transpose Up/Down for sample map. - [New] <Jojo> VST/Instrument handling: The IT instrument note mapping is now also applied to VST instruments (before, it was just available for samples). This way, VST instruments can be transposed easily. - [Imp] <Jojo> When pasting an envelope, it's now also automatically enabled. - [Imp] <Jojo> Instrument name and filename are now properly limited in length. - [Imp] <Jojo> "Scale envelope points" is now always available for scaling the values of the points (y axis). - [Fix] <Jojo> The panning spin button ranged from 0 to 256, however when saving to .IT, 256 was wrapping over to 0. Panning is now limited from 0 to 255. - [Fix] <Jojo> It was impossible to assign plugin slot 100 to an instrument. + [New] <Jojo> Envelope zooming. Might still look very weird (especially the first tick and around loop points). Includes two new keyboard shortcuts. + [New] <Jojo> Transpose Up/Down for sample map. + [New] <Jojo> VST/Instrument handling: The IT instrument note mapping is now also applied to VST instruments (before, it was just available for samples). This way, VST instruments can be transposed easily. + [Imp] <Jojo> When pasting an envelope, it's now also automatically enabled. + [Imp] <Jojo> Instrument name and filename are now properly limited in length. + [Imp] <Jojo> "Scale envelope points" is now always available for scaling the values of the points (y axis). + [Fix] <Jojo> The panning spin button ranged from 0 to 256, however when saving to .IT, 256 was wrapping over to 0. Panning is now limited from 0 to 255. + [Fix] <Jojo> It was impossible to assign plugin slot 100 to an instrument. Comments tab - [Fix] <Jojo> Correct C-5 frequency is now also shown if the module is an XM file. - [Fix] <Jojo> When editing sample / instrument names, they are limited properly in length now. + [Fix] <Jojo> Correct C-5 frequency is now also shown if the module is an XM file. + [Fix] <Jojo> When editing sample / instrument names, they are limited properly in length now. Treeview - [New] <Jojo> Sequences can now be copied to other modules by simply dragging the sequence header into the the other module's sequence header. Does only work between two different modules, not within the same module, and it will not copy the pattern contents. - [Imp] <Jojo> Display sequence index next to sequence names. - [Imp] <Jojo> Improved order dragging; It is now also possible to drag an order into a non-MPTM module. In that case, the old orderlist will be replaced. - [Imp] <Jojo> J2B files were not shown in treeview. - [Fix] <Jojo> Soundfont samples were not playing correctly anymore. Note that soundfont samples in the MIDI library still don't work. - [Fix] <Jojo> A crash could occour if the instrument library path was too long (f.e. because of malicious strings in the [Paths] section of the INI file) - [Fix] <Jojo> "Bypass" action for VSTs didn't set the document as modified. - [Fix] <Jojo> Right-Click on module -> Close didn't ask for confirmation when the document was modified. - [Fix] <Jojo> Insert/Duplicate sequence actions didn't set the document modified. Grey out those two actions if no additional sequences can be added. + [New] <Jojo> Sequences can now be copied to other modules by simply dragging the sequence header into the the other module's sequence header. Does only work between two different modules, not within the same module, and it will not copy the pattern contents. + [Imp] <Jojo> Display sequence index next to sequence names. + [Imp] <Jojo> Improved order dragging; It is now also possible to drag an order into a non-MPTM module. In that case, the old orderlist will be replaced. + [Imp] <Jojo> J2B files were not shown in treeview. + [Fix] <Jojo> Soundfont samples were not playing correctly anymore. Note that soundfont samples in the MIDI library still don't work. + [Fix] <Jojo> A crash could occour if the instrument library path was too long (f.e. because of malicious strings in the [Paths] section of the INI file) + [Fix] <Jojo> "Bypass" action for VSTs didn't set the document as modified. + [Fix] <Jojo> Right-Click on module -> Close didn't ask for confirmation when the document was modified. + [Fix] <Jojo> Insert/Duplicate sequence actions didn't set the document modified. Grey out those two actions if no additional sequences can be added. VST - [New] <Jojo> VST/Instrument handling: The IT instrument note mapping is now also applied to VST instruments (before, it was just available for samples). This way, VST instruments can be transposed easily. - [Imp] <Jojo> VST Editor: Instead of just saying the user that the plugin has to be assigned to an instrument to play notes, they are queried now whether they want to automatically add an instrument. - [Imp] <Jojo> VST Editor: Added shortcuts for "toggle bypass", "pass keys to plug" and "record params to pattern" - [Mod] <Jojo> VST Editor: Changed number of patches per sub menu from 100 to 128. Now, one sub menu equals ones MIDI bank (more logical) - [Fix] <Jojo> VST Editor: Preset names starting with ' ' >= char > 'A' were cropped (i.e. "123ABC" was displayed as "ABC") - [Fix] <Jojo> Even if an instrument was muted, a VSTi assigned to this instrument was still playing in the pattern. - [Fix] <re> Some VSTs that previously wouldn't load might now load fine. - [Fix] <re> Returned host CanDo-values were wrong (since pre RC1 era). - + [New] <Jojo> VST/Instrument handling: The IT instrument note mapping is now also applied to VST instruments (before, it was just available for samples). This way, VST instruments can be transposed easily. + [Imp] <Jojo> VST Editor: Instead of just saying the user that the plugin has to be assigned to an instrument to play notes, they are queried now whether they want to automatically add an instrument. + [Imp] <Jojo> VST Editor: Added shortcuts for "toggle bypass", "pass keys to plug" and "record params to pattern" + [Mod] <Jojo> VST Editor: Changed number of patches per sub menu from 100 to 128. Now, one sub menu equals ones MIDI bank (more logical) + [Fix] <Jojo> VST Editor: Preset names starting with ' ' >= char > 'A' were cropped (i.e. "123ABC" was displayed as "ABC") + [Fix] <Jojo> Even if an instrument was muted, a VSTi assigned to this instrument was still playing in the pattern. + [Fix] <re> Some VSTs that previously wouldn't load might now load fine. + [Fix] <re> Returned host CanDo-values were wrong (since pre RC1 era). + Mod conversion - [Fix] <Jojo> When converting from MOD to S3M or IT, the Invert Loop effect was not removed. - [Fix] <Jojo> When converting from MPTM to another format, the first sequence name is removed and the sequence is now sized properly when merging multiple sequences (tx Skaven). - [Fix] <Jojo> When converting between XM and IT, the sample autovibrato "sweep" factor is now fixed a bit (since sweep = 0 equals "no sweep" in XM, and "no vibrato" in IT). - [Fix] <Jojo> When removing instruments from the treeview and converting the module to a different format which also supports instruments, OpenMPT crashed. - [Fix] <Jojo> When converting to MOD/S3M, the extended filter range flag was not deactivated. - [Fix] <Jojo> S00 (IT/S3M) does not equal E00 (MOD/XM), as Exx doesn't have effect memory. Trying to convert S00 to the last used value now. - [Fix] <Jojo> If necessary (S3M), reset restart position attribute when converting - [Fix] <re> Merging multiple sequences didn't properly convert '---'/'+++' orders. - + [Fix] <Jojo> When converting from MOD to S3M or IT, the Invert Loop effect was not removed. + [Fix] <Jojo> When converting from MPTM to another format, the first sequence name is removed and the sequence is now sized properly when merging multiple sequences (tx Skaven). + [Fix] <Jojo> When converting between XM and IT, the sample autovibrato "sweep" factor is now fixed a bit (since sweep = 0 equals "no sweep" in XM, and "no vibrato" in IT). + [Fix] <Jojo> When removing instruments from the treeview and converting the module to a different format which also supports instruments, OpenMPT crashed. + [Fix] <Jojo> When converting to MOD/S3M, the extended filter range flag was not deactivated. + [Fix] <Jojo> S00 (IT/S3M) does not equal E00 (MOD/XM), as Exx doesn't have effect memory. Trying to convert S00 to the last used value now. + [Fix] <Jojo> If necessary (S3M), reset restart position attribute when converting + [Fix] <re> Merging multiple sequences didn't properly convert '---'/'+++' orders. + IT - [Imp] <Jojo> IT Saver: Compatibility export saves stereo samples again, as other tracker like Schism also support this. - [Fix] <Jojo> IT Saver: Fixed IT sample flags which could potentionally cause IT to screw up on loading/saving MPT-made modules with samples that are not used by an instrument. - [Fix] <Jojo> IT Loader: ChibiTracker uses \n instead of \r in the IT comment text, which was not handled properly. - [Fix] <Jojo> (fix from SchismTracker) IT Loader: Ignore stereo sample flag when loading old IT files (older than IT 2.14) since Impulse Tracker did not reset this flag when importing stereo samples back then. - [Fix] <Jojo> ITI/ITS Loader: Sample flags were not reset when a sample slot was overwritten when loading ITI or ITS files. That way, it was possible that f.e. the bidi loop flag was not disabled when loading a new sample that had a normal loop. - [Fix] <Jojo> S3M/IT compatibility: Note Cut really cuts notes and does not just mute them (so that following volume commands could restore the sample) - [Fix] <Jojo> IT Compatibility: Always reset autovibrato settings when there's an instrument number (fix from SchismTracker) - [Fix] <Jojo> IT Compatibility: S77 / S79/ S7B are supposed to pause the envelope, not disable it. - [Fix] <Jojo> IT Compatibility: ignore slide commands with both nibbles set (f.e. D55, PA1, ...) - [Fix] <Jojo> IT Compatibility: Default Vibrato/Tremolo/Panbrello waveform values to sine waveform if out of range (e.g. S35) + [Imp] <Jojo> IT Saver: Compatibility export saves stereo samples again, as other tracker like Schism also support this. + [Fix] <Jojo> IT Saver: Fixed IT sample flags which could potentially cause IT to screw up on loading/saving MPT-made modules with samples that are not used by an instrument. + [Fix] <Jojo> IT Loader: ChibiTracker uses \n instead of \r in the IT comment text, which was not handled properly. + [Fix] <Jojo> (fix from SchismTracker) IT Loader: Ignore stereo sample flag when loading old IT files (older than IT 2.14) since Impulse Tracker did not reset this flag when importing stereo samples back then. + [Fix] <Jojo> ITI/ITS Loader: Sample flags were not reset when a sample slot was overwritten when loading ITI or ITS files. That way, it was possible that f.e. the bidi loop flag was not disabled when loading a new sample that had a normal loop. + [Fix] <Jojo> S3M/IT compatibility: Note Cut really cuts notes and does not just mute them (so that following volume commands could restore the sample) + [Fix] <Jojo> IT Compatibility: Always reset autovibrato settings when there's an instrument number (fix from SchismTracker) + [Fix] <Jojo> IT Compatibility: S77 / S79/ S7B are supposed to pause the envelope, not disable it. + [Fix] <Jojo> IT Compatibility: ignore slide commands with both nibbles set (f.e. D55, PA1, ...) + [Fix] <Jojo> IT Compatibility: Default Vibrato/Tremolo/Panbrello waveform values to sine waveform if out of range (e.g. S35) IT/MPTM/ITP, Instrument extension handling: - [Fix] <re> Fixes to instrument envelope flag handling (broken in 1.18.00.00). - + [Fix] <re> Fixes to instrument envelope flag handling (broken in 1.18.00.00). + XM - [Imp] <Jojo> XM Loader: Improved detection of an old version of MPT (1.09?). - [Fix] <Jojo> XM Loader: Some XMs not made with ModPlug were recognized as files made with MPT. - [Fix] <Jojo> XM Loader: The last XM instrument was not always loaded. - [Fix] <Jojo> XM Loader: Early versions of Skale Tracker (R.I.P.) apparently did stupid things to XM instrument headers, so mpt failed to load such modules. Tested the fix with a few hundred XMs and apparently only one XM (IFULOVE.XM) that I have has a header size that is different from the struct size - and that's the one that caused problems. - [Fix] <Jojo> XM Compatibility: Volume column doesn't have an effect memory, most effects with param = 0 are useless. Those are ignored in compatibility mode playback and also when exporting the file in compatibility mode. - [Fix] <Jojo> XM Compatibility: Improved handling of the situation when a 3xx effect was used, but previously no note was playing. - [Fix] <Jojo> XM Compatibility: New instrument + tone portamento = ignore new instrument (fixes partytime.xm by cancer) - + [Imp] <Jojo> XM Loader: Improved detection of an old version of MPT (1.09?). + [Fix] <Jojo> XM Loader: Some XMs not made with ModPlug were recognized as files made with MPT. + [Fix] <Jojo> XM Loader: The last XM instrument was not always loaded. + [Fix] <Jojo> XM Loader: Early versions of Skale Tracker (R.I.P.) apparently did stupid things to XM instrument headers, so mpt failed to load such modules. Tested the fix with a few hundred XMs and apparently only one XM (IFULOVE.XM) that I have has a header size that is different from the struct size - and that's the one that caused problems. + [Fix] <Jojo> XM Compatibility: Volume column doesn't have an effect memory, most effects with param = 0 are useless. Those are ignored in compatibility mode playback and also when exporting the file in compatibility mode. + [Fix] <Jojo> XM Compatibility: Improved handling of the situation when a 3xx effect was used, but previously no note was playing. + [Fix] <Jojo> XM Compatibility: New instrument + tone portamento = ignore new instrument (fixes partytime.xm by cancer) + MOD - [Imp] <Jojo> Module creation: When creating a new .MOD, it has 31 sample slots by default. - [Imp] <Jojo> Playback: When the PT1x flag is activated, Amiga note range limits are automatically taken into account. - [Fix] <Jojo> MOD Saving: Samples were shifted badly if the sample size was odd. (wow, this is an OLD bug!) - [Fix] <Jojo> MOD Saving: If a sample had loop points set, but loop disabled, they were still saved in the .MOD file, resulting in the loop being enabled automatically. - [Fix] <Jojo> MOD Loader: Very short loops (4-8 bytes long) are not ignored anymore. This fixes "Crew Generation" by Necros. - + [Imp] <Jojo> Module creation: When creating a new .MOD, it has 31 sample slots by default. + [Imp] <Jojo> Playback: When the PT1x flag is activated, Amiga note range limits are automatically taken into account. + [Fix] <Jojo> MOD Saving: Samples were shifted badly if the sample size was odd. (wow, this is an OLD bug!) + [Fix] <Jojo> MOD Saving: If a sample had loop points set, but loop disabled, they were still saved in the .MOD file, resulting in the loop being enabled automatically. + [Fix] <Jojo> MOD Loader: Very short loops (4-8 bytes long) are not ignored anymore. This fixes "Crew Generation" by Necros. + S3M - [Imp] <Jojo> S3M Loader: Display a message if an S3M file contains Adlib instruments (rare). - [Fix] <Jojo> S3M Playback: In ST3, muted channels are completely ignored, not even effects are interpreted. Let's try this in MPT, too. - [Fix] <Jojo> S3M Compatibility: Slightly better handling of vibrato/tremolo waveform types (although the ST3 help screen says that continuous vibrato/tremolo is possible, it does actually not work.) - [Reg] <Jojo> Cannot create S3M files with more than 100 patterns anymore, because... - [Fix] <Jojo> ... it was possible to create S3M files where the 256 parapointers were not enough, resulting in incomplete/broken files. - [Fix] <Jojo> S3M/IT Compatibility: Note Cut really cuts notes and does not just mute them (so that following volume commands could restore the sample) - -Other modules: - [Imp] <Jojo> MT2 Loader (MadTracker): Make use of the "lines per beat" header field. Release node is not set anymore for each and every instrument envelope. MT2 files are now loaded as IT files by default (instead of XM) because of their extended instrument properties (NNAs, filters, etc) - I wonder what this breaks, but I don't bother much because MT2 support was already 100% broken before this. :) Some MT example tunes sound a bit better now at least. - [Fix] <Jojo> PTM Loader: Fixed an unhandled null pointer exception that occured when loading some unsupported RAR files. - [Fix] <Jojo> PSM16 Loader: Fix for note cut on tick 0 (warbot tune from Silverball) - [Fix] <Jojo> 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. - [Fix] <Jojo> DBM Loader: Various fixes to increase import precision and an endianness fix - [Fix] <Jojo> AMF DSM Loader: Made some changes to the pattern reader, which elimiante the strange "vC7" commands in the pattern. I have found no hints on whether my fix is correct or not, apart from the fact that those AMF files that I have play a lot better now. And it makes kind of sense... - [Fix] <Jojo> IMF Loader: Some fixes copied from Schism (copied from MikMod) + [Imp] <Jojo> S3M Loader: Display a message if an S3M file contains Adlib instruments (rare). + [Fix] <Jojo> S3M Playback: In ST3, muted channels are completely ignored, not even effects are interpreted. Let's try this in MPT, too. + [Fix] <Jojo> S3M Compatibility: Slightly better handling of vibrato/tremolo waveform types (although the ST3 help screen says that continuous vibrato/tremolo is possible, it does actually not work.) + [Reg] <Jojo> Cannot create S3M files with more than 100 patterns anymore, because... + [Fix] <Jojo> ... it was possible to create S3M files where the 256 parapointers were not enough, resulting in incomplete/broken files. + [Fix] <Jojo> S3M/IT Compatibility: Note Cut really cuts notes and does not just mute them (so that following volume commands could restore the sample) MPTM - [New] <rewbs> Added combined note delay & note cut command for MPTM only (":xy" means delay until tick x and play for y ticks). - [New] <Jojo> MPTM command S7D explicitely enforces pitch envelope, S7E enforces filter envelope. - [Fix] <Jojo> MPTM Saving: A missing null pointer check crashed OpenMPT when trying to access a deleted instrument slot. + [New] <rewbs> Added combined note delay & note cut command for MPTM only (":xy" means delay until tick x and play for y ticks). + [New] <Joj... [truncated message content] |
From: <sag...@us...> - 2010-08-02 21:40:19
|
Revision: 668 http://modplug.svn.sourceforge.net/modplug/?rev=668&view=rev Author: saga-games Date: 2010-08-02 21:40:13 +0000 (Mon, 02 Aug 2010) Log Message: ----------- [Imp] Removed warning when converting from MPTM to another format (the possibility of losing data is always there, and there's a log for that anyway). Instrument tunings are now also removed properly when converting from MPTM. [Fix] Channel names in AMS files (Extreme's Tracker) are now loaded properly. [Ref] Some changes here and there. Modified Paths: -------------- trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/Load_s3m.cpp trunk/OpenMPT/soundlib/Message.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2010-08-02 21:40:13 UTC (rev 668) @@ -460,7 +460,7 @@ if(m_SndFile.instrumentModified[i]) { unsavedInstrument = true; break; } } - if(unsavedInstrument && ::MessageBox(NULL,"Do you want to save modified instruments ?",NULL,MB_ICONQUESTION | MB_YESNO | MB_APPLMODAL) == IDYES){ + if(unsavedInstrument && ::MessageBox(NULL,"Do you want to save modified instruments?",NULL,MB_ICONQUESTION | MB_YESNO | MB_APPLMODAL) == IDYES){ for(INSTRUMENTINDEX i = 0 ; i < m_SndFile.m_nInstruments ; i++){ if(m_SndFile.m_szInstrumentPath[i][0] != '\0'){ @@ -2042,7 +2042,8 @@ double bpm = CMainFrame::GetMainFrame()->GetApproxBPM(); - switch(m_SndFile.m_nTempoMode) { + switch(m_SndFile.m_nTempoMode) + { case tempo_mode_alternative: Message.Format("Using alternative tempo interpretation.\n\nAssuming:\n. %d ticks per second\n. %d ticks per row\n. %d rows per beat\nthe tempo is approximately: %.20g BPM", m_SndFile.m_nMusicTempo, m_SndFile.m_nMusicSpeed, m_SndFile.m_nRowsPerBeat, bpm); Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/mptrack/Moddoc.h 2010-08-02 21:40:13 UTC (rev 668) @@ -218,8 +218,8 @@ // operations public: - BOOL ChangeModType(MODTYPE wType); - BOOL ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg = true); + bool ChangeModType(MODTYPE wType); + bool ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg = true); BOOL ConvertInstrumentsToSamples(); UINT RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]); Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-08-02 21:40:13 UTC (rev 668) @@ -19,8 +19,6 @@ static char THIS_FILE[] = __FILE__; #endif -#define str_mptm_conversion_warning GetStrI18N(_TEXT("Conversion from mptm to any other moduletype may makes certain features unavailable and is not guaranteed to work properly. Do the conversion anyway?")) - const size_t Pow10Table[10] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; // Return D'th digit(character) of given value. @@ -37,7 +35,7 @@ ////////////////////////////////////////////////////////////////////// // Module type conversion -BOOL CModDoc::ChangeModType(MODTYPE nNewType) +bool CModDoc::ChangeModType(MODTYPE nNewType) //------------------------------------------- { CHAR s[256]; @@ -50,10 +48,11 @@ // This is because ITP is a HACK and doesn't genuinely change m_nType, // but uses flages instead. ChangeFileExtension(nNewType); - return TRUE; + return true; } - if(nNewType == nOldType) return TRUE; + if(nNewType == nOldType) + return true; const bool oldTypeIsMOD = (nOldType == MOD_TYPE_MOD), oldTypeIsXM = (nOldType == MOD_TYPE_XM), oldTypeIsS3M = (nOldType == MOD_TYPE_S3M), oldTypeIsIT = (nOldType == MOD_TYPE_IT), @@ -70,40 +69,38 @@ const CModSpecifications& specs = m_SndFile.GetModSpecifications(nNewType); - if(oldTypeIsMPT) - { - if(::MessageBox(NULL, str_mptm_conversion_warning, 0, MB_YESNO) != IDYES) - return FALSE; + /* + Incomplete list of MPTm-only features and extensions in the old formats: - /* - Incomplete list of MPTm-only features and extensions in the old formats: + Features only available for MPTm: + -User definable tunings. + -Extended pattern range + -Extended sequence + -Multiple sequences ("songs") + -Pattern-specific time signatures + -Pattern effects :xy, S7D, S7E + -Long instrument envelopes + -Envelope release node (this was previously also usable in the IT format, but is deprecated in that format) - Features only available for MPTm: - -User definable tunings. - -Extended pattern range - -Extended sequence - -Multiple sequences + Extended features in IT/XM/S3M/MOD(not all listed below are available in all of those formats): + -plugs + -Extended ranges for + -sample count + -instrument count + -pattern count + -sequence size + -Row count + -channel count + -tempo limits + -Extended sample/instrument properties. + -MIDI mapping directives + -Versioninfo + -channel names + -pattern names + -Alternative tempomodes + -For more info, see e.g. SaveExtendedSongProperties(), SaveExtendedInstrumentProperties() + */ - Extended features in IT/XM/S3M/MOD(not all listed below are available in all of those formats): - -plugs - -Extended ranges for - -sample count - -instrument count - -pattern count - -sequence size - -Row count - -channel count - -tempo limits - -Extended sample/instrument properties. - -MIDI mapping directives - -Versioninfo - -channel names - -pattern names - -Alternative tempomodes - -For more info, see e.g. SaveExtendedSongProperties(), SaveExtendedInstrumentProperties() - */ - } - // Check if conversion to 64 rows is necessary for (UINT ipat=0; ipat<m_SndFile.Patterns.Size(); ipat++) { @@ -114,7 +111,7 @@ if (::MessageBox(NULL, "This operation will convert all instruments to samples,\n" "and resize all patterns to 64 rows.\n" - "Do you want to continue?", "Warning", MB_YESNO | MB_ICONQUESTION) != IDYES) return FALSE; + "Do you want to continue?", "Warning", MB_YESNO | MB_ICONQUESTION) != IDYES) return false; BeginWaitCursor(); BEGIN_CRITICAL(); // Converting instruments to samples @@ -278,7 +275,7 @@ if (oldTypeIsIT_MPT && newTypeIsXM) { bool bBrokenNoteMap = false, bBrokenSustainLoop = false; - for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.m_nInstruments; nIns++) + for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.GetNumInstruments(); nIns++) { MODINSTRUMENT *pIns = m_SndFile.Instruments[nIns]; if (pIns) @@ -314,6 +311,24 @@ if (bBrokenSustainLoop) AddToLog("WARNING: Sustain loops were converted to sustain points.\n"); } + // Instrument tunings + if(oldTypeIsMPT) + { + bool bFirstWarn = true; + for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.GetNumInstruments(); nIns++) + { + if(m_SndFile.Instruments[nIns] != nullptr && m_SndFile.Instruments[nIns]->pTuning != nullptr) + { + m_SndFile.Instruments[nIns]->SetTuning(nullptr); + if(bFirstWarn) + { + AddToLog("WARNING: Instrument tunings will be lost!\n"); + bFirstWarn = false; + } + } + } + } + if(newTypeIsMOD) { // Not supported in MOD format @@ -396,7 +411,7 @@ GetSampleUndo()->ClearUndo(); UpdateAllViews(NULL, HINT_MODTYPE | HINT_MODGENERAL); EndWaitCursor(); - return TRUE; + return true; } // Trim envelopes and remove release nodes. @@ -437,7 +452,7 @@ // Change the number of channels -BOOL CModDoc::ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg) +bool CModDoc::ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg) //---------------------------------------------------------------------------------- { const CHANNELINDEX maxChans = m_SndFile.GetModSpecifications().channelsMax; @@ -446,10 +461,10 @@ CString error; error.Format("Error: Max number of channels for this file type is %d", maxChans); ::AfxMessageBox(error, MB_OK|MB_ICONEXCLAMATION); - return FALSE; + return false; } - if (nNewChannels == m_SndFile.m_nChannels) return FALSE; + if (nNewChannels == m_SndFile.m_nChannels) return false; if (nNewChannels < m_SndFile.m_nChannels) { UINT nChnToRemove = 0; @@ -466,7 +481,7 @@ CRemoveChannelsDlg rem(&m_SndFile, nChnToRemove, showCancelInRemoveDlg); CheckUnusedChannels(rem.m_bChnMask, nFound); - if (rem.DoModal() != IDOK) return FALSE; + if (rem.DoModal() != IDOK) return false; // Removing selected channels RemoveChannels(rem.m_bChnMask); @@ -483,7 +498,7 @@ { END_CRITICAL(); AddToLog("ERROR: Not enough memory to create new channels!\nPattern Data is corrupted!\n"); - return FALSE; + return false; } for (UINT j=0; j<m_SndFile.Patterns[i].GetNumRows(); j++) { @@ -507,7 +522,7 @@ SetModified(); GetPatternUndo()->ClearUndo(); UpdateAllViews(NULL, HINT_MODTYPE); - return TRUE; + return true; } Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2010-08-02 21:40:13 UTC (rev 668) @@ -139,7 +139,7 @@ BYTE chnnamlen = lpStream[dwMemPos++]; if ((chnnamlen) && (chnnamlen < MAX_CHANNELNAME)) { - memcpy(ChnSettings[cNam].szName, lpStream + dwMemPos + 1, chnnamlen); + memcpy(ChnSettings[cNam].szName, lpStream + dwMemPos, chnnamlen); SpaceToNullStringFixed(ChnSettings[cNam].szName, chnnamlen); } dwMemPos += chnnamlen; Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-08-02 21:40:13 UTC (rev 668) @@ -380,7 +380,7 @@ insfile[iSmp] = ((DWORD)LittleEndianW(*((LPWORD)(s+0x0E)))) << 4; insfile[iSmp] += ((DWORD)(BYTE)s[0x0D]) << 20; - if (insfile[iSmp] > dwMemLength) insfile[iSmp] &= 0xFFFF; + if (insfile[iSmp] > dwMemLength) insfile[iSmp] &= 0xFFFF; // wtf? whose idea was this? if(Samples[iSmp].nLoopEnd < 2) Samples[iSmp].nLoopStart = Samples[iSmp].nLoopEnd = 0; Modified: trunk/OpenMPT/soundlib/Message.cpp =================================================================== --- trunk/OpenMPT/soundlib/Message.cpp 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/soundlib/Message.cpp 2010-08-02 21:40:13 UTC (rev 668) @@ -151,7 +151,7 @@ // [in] data: pointer to the data in memory that is going to be read // [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). // [in] lineLength: The fixed length of a line. -// [in] lineEndingLength: The padding space between two fikxed lines. (there could for example be a null char after every line) +// [in] lineEndingLength: The padding space between two fixed lines. (there could for example be a null char after every line) // [in] pTextConverter: Pointer to a callback function which can be used to pre-process the read characters, if necessary (nullptr otherwise). // [out] returns true on success. bool CSoundFile::ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength, void (*pTextConverter)(char &)) Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2010-08-01 22:20:31 UTC (rev 667) +++ trunk/OpenMPT/soundlib/Sndfile.h 2010-08-02 21:40:13 UTC (rev 668) @@ -972,7 +972,7 @@ // [in] data: pointer to the data in memory that is going to be read // [in] length: number of characters that should be read, not including a possible trailing null terminator (it is automatically appended). // [in] lineLength: The fixed length of a line. - // [in] lineEndingLength: The padding space between two fikxed lines. (there could for example be a null char after every line) + // [in] lineEndingLength: The padding space between two fixed lines. (there could for example be a null char after every line) // [in] pTextConverter: Pointer to a callback function which can be used to pre-process the read characters, if necessary (nullptr otherwise). // [out] returns true on success. bool ReadFixedLineLengthMessage(const BYTE *data, const size_t length, const size_t lineLength, const size_t lineEndingLength, void (*pTextConverter)(char &) = nullptr); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-08-03 15:26:04
|
Revision: 669 http://modplug.svn.sourceforge.net/modplug/?rev=669&view=rev Author: saga-games Date: 2010-08-03 15:25:56 +0000 (Tue, 03 Aug 2010) Log Message: ----------- [Ref] Moved ITP loader/saver to its own file, as it does not really have something in common with the IT loader. Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/soundlib/IT_DEFS.H trunk/OpenMPT/soundlib/Load_it.cpp Added Paths: ----------- trunk/OpenMPT/soundlib/Load_itp.cpp Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2010-08-02 21:40:13 UTC (rev 668) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2010-08-03 15:25:56 UTC (rev 669) @@ -289,6 +289,9 @@ RelativePath="..\soundlib\Load_it.cpp"> </File> <File + RelativePath="..\soundlib\Load_itp.cpp"> + </File> + <File RelativePath="..\soundlib\load_j2b.cpp"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-08-02 21:40:13 UTC (rev 668) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-08-03 15:25:56 UTC (rev 669) @@ -389,6 +389,10 @@ > </File> <File + RelativePath="..\soundlib\Load_itp.cpp" + > + </File> + <File RelativePath="..\soundlib\load_j2b.cpp" > </File> Modified: trunk/OpenMPT/soundlib/IT_DEFS.H =================================================================== --- trunk/OpenMPT/soundlib/IT_DEFS.H 2010-08-02 21:40:13 UTC (rev 668) +++ trunk/OpenMPT/soundlib/IT_DEFS.H 2010-08-03 15:25:56 UTC (rev 669) @@ -140,9 +140,6 @@ extern BYTE autovibit2xm[8]; extern BYTE autovibxm2it[8]; -#define ITP_VERSION 0x00000102 // v1.02 -#define ITP_FILE_ID 0x2e697470 // .itp ASCII - #define IT_CHBI 0x49424843 // "CHBI" magic bytes in the IT header to identify ChibiTracker enum IT_ReaderBitMasks Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-08-02 21:40:13 UTC (rev 668) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-08-03 15:25:56 UTC (rev 669) @@ -8,11 +8,6 @@ */ #include "stdafx.h" -// -> CODE#0023 -// -> DESC="IT project files (.itp)" -#include "../mptrack/mptrack.h" -#include "../mptrack/mainfrm.h" -// -! NEW_FEATURE#0023 #include "sndfile.h" #include "it_defs.h" #include "tuningcollection.h" @@ -46,8 +41,6 @@ */ - - static bool AreNonDefaultTuningsUsed(CSoundFile& sf) //-------------------------------------------------- { @@ -456,448 +449,7 @@ return returnVal; //return offset } -// -> CODE#0023 -// -> DESC="IT project files (.itp)" -bool CSoundFile::ReadITProject(LPCBYTE lpStream, const DWORD dwMemLength) -//----------------------------------------------------------------------- -{ - UINT i,n,nsmp; - DWORD id,len,size; - DWORD streamPos = 0; - DWORD version; - // Macro used to make sure that given amount of bytes can be read. - // Returns FALSE from this function if reading is not possible. - #define ASSERT_CAN_READ(x) \ - if( streamPos > dwMemLength || x > dwMemLength - streamPos ) return false; - - ASSERT_CAN_READ(12); - -// Check file ID - - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - if(id != ITP_FILE_ID) return false; - streamPos += sizeof(DWORD); - - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - version = id; - streamPos += sizeof(DWORD); - - m_nType = MOD_TYPE_IT; - -// Song name - - // name string length - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - len = id; - streamPos += sizeof(DWORD); - - // name string - ASSERT_CAN_READ(len); - if (len<=sizeof(m_szNames[0])) { - memcpy(m_szNames[0],lpStream+streamPos,len); - streamPos += len; - m_szNames[0][sizeof(m_szNames[0])-1] = '\0'; - } - else return false; - -// Song comments - - // comment string length - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - streamPos += sizeof(DWORD); - if(id > uint16_max) return false; - - // allocate and copy comment string - ASSERT_CAN_READ(id); - if(id > 0) - { - ReadMessage(lpStream + streamPos, id - 1, leCR); - } - streamPos += id; - -// Song global config - ASSERT_CAN_READ(5*4); - - // m_dwSongFlags - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_dwSongFlags = id; - streamPos += sizeof(DWORD); - - if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; - - // m_nDefaultGlobalVolume - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nDefaultGlobalVolume = id; - streamPos += sizeof(DWORD); - - // m_nSamplePreAmp - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nSamplePreAmp = id; - streamPos += sizeof(DWORD); - - // m_nDefaultSpeed - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nDefaultSpeed = id; - streamPos += sizeof(DWORD); - - // m_nDefaultTempo - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nDefaultTempo = id; - streamPos += sizeof(DWORD); - -// Song channels data - ASSERT_CAN_READ(2*4); - - // m_nChannels - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nChannels = id; - streamPos += sizeof(DWORD); - if(m_nChannels > 127) return false; - - // channel name string length (=MAX_CHANNELNAME) - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - len = id; - streamPos += sizeof(DWORD); - if(len > MAX_CHANNELNAME) return false; - - // Channels' data - for(i=0; i<m_nChannels; i++){ - ASSERT_CAN_READ(3*4 + len); - - // ChnSettings[i].nPan - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - ChnSettings[i].nPan = id; - streamPos += sizeof(DWORD); - - // ChnSettings[i].dwFlags - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - ChnSettings[i].dwFlags = id; - streamPos += sizeof(DWORD); - - // ChnSettings[i].nVolume - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - ChnSettings[i].nVolume = id; - streamPos += sizeof(DWORD); - - // ChnSettings[i].szName - memcpy(&ChnSettings[i].szName[0],lpStream+streamPos,len); - SetNullTerminator(ChnSettings[i].szName); - streamPos += len; - } - -// Song mix plugins - // size of mix plugins data - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - streamPos += sizeof(DWORD); - - // mix plugins - ASSERT_CAN_READ(id); - streamPos += LoadMixPlugins(lpStream+streamPos, id); - -// Song midi config - - // midi cfg data length - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - streamPos += sizeof(DWORD); - - // midi cfg - ASSERT_CAN_READ(id); - if (id<=sizeof(m_MidiCfg)) { - memcpy(&m_MidiCfg,lpStream+streamPos,id); - streamPos += id; - } - -// Song Instruments - - // m_nInstruments - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nInstruments = id; - if(m_nInstruments > MAX_INSTRUMENTS) return false; - streamPos += sizeof(DWORD); - - // path string length (=_MAX_PATH) - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - len = id; - if(len > _MAX_PATH) return false; - streamPos += sizeof(DWORD); - - // instruments' paths - for(i=0; i<m_nInstruments; i++){ - ASSERT_CAN_READ(len); - memcpy(&m_szInstrumentPath[i][0],lpStream+streamPos,len); - SetNullTerminator(m_szInstrumentPath[i]); - streamPos += len; - } - -// Song Orders - - // size of order array (=MAX_ORDERS) - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - size = id; - if(size > MAX_ORDERS) return false; - streamPos += sizeof(DWORD); - - // order data - ASSERT_CAN_READ(size); - Order.ReadAsByte(lpStream+streamPos, size, dwMemLength-streamPos); - streamPos += size; - - - -// Song Patterns - - ASSERT_CAN_READ(3*4); - // number of patterns (=MAX_PATTERNS) - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - size = id; - streamPos += sizeof(DWORD); - if(size > MAX_PATTERNS) return false; - - // m_nPatternNames - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - m_nPatternNames = id; - streamPos += sizeof(DWORD); - - // pattern name string length (=MAX_PATTERNNAME) - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - len = id; - streamPos += sizeof(DWORD); - - // m_lpszPatternNames - if (len<=MAX_PATTERNNAME && m_nPatternNames<=MAX_PATTERNS) - { - m_lpszPatternNames = new char[m_nPatternNames * len]; - ASSERT_CAN_READ(m_nPatternNames * len); - memcpy(&m_lpszPatternNames[0],lpStream+streamPos,m_nPatternNames * len); - } - else return false; - - streamPos += m_nPatternNames * len; - - // modcommand data length - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - n = id; - if(n != 6) return false; - streamPos += sizeof(DWORD); - - for(UINT npat=0; npat<size; npat++){ - - // Free pattern if not empty - if(Patterns[npat]) { FreePattern(Patterns[npat]); Patterns[npat] = NULL; } - - // Patterns[npat].GetNumRows() - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - if(id > MAX_PATTERN_ROWS) return false; - Patterns[npat].Resize(id, false); - streamPos += sizeof(DWORD); - - // Try to allocate & read only sized patterns - if(Patterns[npat].GetNumRows()){ - - // Allocate pattern - if(Patterns.Insert(npat, Patterns[npat].GetNumRows())){ - streamPos += m_nChannels * Patterns[npat].GetNumRows() * n; - continue; - } - - // Pattern data - long datasize = m_nChannels * Patterns[npat].GetNumRows() * n; - //if (streamPos+datasize<=dwMemLength) { - if(Patterns[npat].ReadITPdata(lpStream, streamPos, datasize, dwMemLength)) - { - ErrorBox(IDS_ERR_FILEOPEN, NULL); - return false; - } - //memcpy(Patterns[npat],lpStream+streamPos,datasize); - //streamPos += datasize; - //} - } - } - -// Load embeded samples - - ITSAMPLESTRUCT pis; - - // Read original number of samples - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - if(id > MAX_SAMPLES) return false; - m_nSamples = id; - streamPos += sizeof(DWORD); - - // Read number of embeded samples - ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - if(id > MAX_SAMPLES) return false; - n = id; - streamPos += sizeof(DWORD); - - // Read samples - for(i=0; i<n; i++){ - - ASSERT_CAN_READ(4 + sizeof(ITSAMPLESTRUCT) + 4); - - // Sample id number - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - nsmp = id; - streamPos += sizeof(DWORD); - - if(nsmp < 1 || nsmp >= MAX_SAMPLES) - return false; - - // Sample struct - memcpy(&pis,lpStream+streamPos,sizeof(ITSAMPLESTRUCT)); - streamPos += sizeof(ITSAMPLESTRUCT); - - // Sample length - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - len = id; - streamPos += sizeof(DWORD); - if(streamPos >= dwMemLength || len > dwMemLength - streamPos) return false; - - // Copy sample struct data - if(pis.id == 0x53504D49) - { - MODSAMPLE *pSmp = &Samples[nsmp]; - memcpy(pSmp->filename, pis.filename, 12); - pSmp->uFlags = 0; - pSmp->nLength = 0; - pSmp->nLoopStart = pis.loopbegin; - pSmp->nLoopEnd = pis.loopend; - pSmp->nSustainStart = pis.susloopbegin; - pSmp->nSustainEnd = pis.susloopend; - pSmp->nC5Speed = pis.C5Speed; - if(!pSmp->nC5Speed) pSmp->nC5Speed = 8363; - if(pis.C5Speed < 256) pSmp->nC5Speed = 256; - pSmp->nVolume = pis.vol << 2; - if(pSmp->nVolume > 256) pSmp->nVolume = 256; - pSmp->nGlobalVol = pis.gvl; - if(pSmp->nGlobalVol > 64) pSmp->nGlobalVol = 64; - if(pis.flags & 0x10) pSmp->uFlags |= CHN_LOOP; - if(pis.flags & 0x20) pSmp->uFlags |= CHN_SUSTAINLOOP; - if(pis.flags & 0x40) pSmp->uFlags |= CHN_PINGPONGLOOP; - if(pis.flags & 0x80) pSmp->uFlags |= CHN_PINGPONGSUSTAIN; - pSmp->nPan = (pis.dfp & 0x7F) << 2; - if(pSmp->nPan > 256) pSmp->nPan = 256; - if(pis.dfp & 0x80) pSmp->uFlags |= CHN_PANNING; - pSmp->nVibType = autovibit2xm[pis.vit & 7]; - pSmp->nVibRate = pis.vis; - pSmp->nVibDepth = pis.vid & 0x7F; - pSmp->nVibSweep = pis.vir; - if(pis.length){ - pSmp->nLength = pis.length; - if (pSmp->nLength > MAX_SAMPLE_LENGTH) pSmp->nLength = MAX_SAMPLE_LENGTH; - UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U; - if (pis.flags & 2){ - flags += 5; - if (pis.flags & 4) flags |= RSF_STEREO; - pSmp->uFlags |= CHN_16BIT; - } - else{ - if (pis.flags & 4) flags |= RSF_STEREO; - } - // Read sample data - ReadSample(&Samples[nsmp], flags, (LPSTR)(lpStream+streamPos), len); - streamPos += len; - memcpy(m_szNames[nsmp], pis.name, 26); - } - } - } - -// Load instruments - - CMappedFile f; - LPBYTE lpFile; - - for(i=0; i<m_nInstruments; i++){ - - if(m_szInstrumentPath[i][0] == '\0' || !f.Open(m_szInstrumentPath[i])) continue; - - len = f.GetLength(); - lpFile = f.Lock(len); - if(!lpFile) { f.Close(); continue; } - - ReadInstrumentFromFile(i+1, lpFile, len); - f.Unlock(); - f.Close(); - } - -// Extra info data - - __int32 fcode = 0; - LPCBYTE ptr = lpStream + min(streamPos, dwMemLength); - - if (streamPos <= dwMemLength - 4) { - fcode = (*((__int32 *)ptr)); - } - -// Embed instruments' header [v1.01] - if(version >= 0x00000101 && m_dwSongFlags & SONG_ITPEMBEDIH && fcode == 'EBIH'){ - // jump embeded instrument header tag - ptr += sizeof(__int32); - - // set first instrument's header as current - i = 1; - - // parse file - while( uintptr_t(ptr - lpStream) <= dwMemLength - 4 && i <= m_nInstruments ) - { - - fcode = (*((__int32 *)ptr)); // read field code - - switch( fcode ) - { - case 'MPTS': goto mpts; //:) // reached end of instrument headers - case 'SEP@': case 'MPTX': - ptr += sizeof(__int32); // jump code - i++; // switch to next instrument - break; - - default: - ptr += sizeof(__int32); // jump field code - ReadExtendedInstrumentProperty(Instruments[i], fcode, ptr, lpStream + dwMemLength); - break; - } - } - } - - //HACK: if we fail on i <= m_nInstruments above, arrive here without having set fcode as appropriate, - // hence the code duplication. - if ( (uintptr_t)(ptr - lpStream) <= dwMemLength - 4 ) - { - fcode = (*((__int32 *)ptr)); - } - - // Song extensions -mpts: - if( fcode == 'MPTS' ) - LoadExtendedSongProperties(MOD_TYPE_IT, ptr, lpStream, dwMemLength); - - m_nMaxPeriod = 0xF000; - m_nMinPeriod = 8; - - if(m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) - { - SetModFlag(MSF_COMPATIBLE_PLAY, false); - SetModFlag(MSF_MIDICC_BUGEMULATION, true); - SetModFlag(MSF_OLDVOLSWING, true); - } - - return true; - - #undef ASSERT_CAN_READ -} -// -! NEW_FEATURE#0023 - bool CSoundFile::ReadIT(const LPCBYTE lpStream, const DWORD dwMemLength) //---------------------------------------------------------------------- { @@ -1570,259 +1122,7 @@ //#define SAVEITTIMESTAMP #pragma warning(disable:4100) -// -> CODE#0023 -// -> DESC="IT project files (.itp)" -bool CSoundFile::SaveITProject(LPCSTR lpszFileName) -//------------------------------------------------- -{ -// Check song type - if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; - - UINT i,j = 0; - for(i = 0 ; i < m_nInstruments ; i++) { if(m_szInstrumentPath[i][0] != '\0' || !Instruments[i+1]) j++; } - if(m_nInstruments && j != m_nInstruments) return false; - -// Open file - - FILE *f; - - if((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return false; - - -// File ID - - DWORD id = ITP_FILE_ID; - fwrite(&id, 1, sizeof(id), f); - - id = ITP_VERSION; - fwrite(&id, 1, sizeof(id), f); - -// Song name - - // name string length - id = 27; - fwrite(&id, 1, sizeof(id), f); - - // song name - fwrite(&m_szNames[0], 1, 27, f); - -// Song comments - - // comment string length - id = m_lpszSongComments ? strlen(m_lpszSongComments)+1 : 0; - fwrite(&id, 1, sizeof(id), f); - - // comment string - if(m_lpszSongComments) fwrite(&m_lpszSongComments[0], 1, strlen(m_lpszSongComments)+1, f); - -// Song global config - - id = m_dwSongFlags; - fwrite(&id, 1, sizeof(id), f); - id = m_nDefaultGlobalVolume; - fwrite(&id, 1, sizeof(id), f); - id = m_nSamplePreAmp; - fwrite(&id, 1, sizeof(id), f); - id = m_nDefaultSpeed; - fwrite(&id, 1, sizeof(id), f); - id = m_nDefaultTempo; - fwrite(&id, 1, sizeof(id), f); - -// Song channels data - - // number of channels - id = m_nChannels; - fwrite(&id, 1, sizeof(id), f); - - // channel name string length - id = MAX_CHANNELNAME; - fwrite(&id, 1, sizeof(id), f); - - // channel config data - for(i=0; i<m_nChannels; i++){ - id = ChnSettings[i].nPan; - fwrite(&id, 1, sizeof(id), f); - id = ChnSettings[i].dwFlags; - fwrite(&id, 1, sizeof(id), f); - id = ChnSettings[i].nVolume; - fwrite(&id, 1, sizeof(id), f); - fwrite(&ChnSettings[i].szName[0], 1, MAX_CHANNELNAME, f); - } - -// Song mix plugins - - // mix plugins data length - id = SaveMixPlugins(NULL, TRUE); - fwrite(&id, 1, sizeof(id), f); - - // mix plugins data - SaveMixPlugins(f, FALSE); - -// Song midi config - - // midi cfg data length - id = sizeof(MODMIDICFG); - fwrite(&id, 1, sizeof(id), f); - - // midi cfg - fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); - -// Song Instruments - - // number of instruments - id = m_nInstruments; - fwrite(&id, 1, sizeof(id), f); - - // path name string length - id = _MAX_PATH; - fwrite(&id, 1, sizeof(id), f); - - // instruments' path - for(i=0; i<m_nInstruments; i++) fwrite(&m_szInstrumentPath[i][0], 1, _MAX_PATH, f); - -// Song Orders - - // order array size - id = Order.size(); - fwrite(&id, 1, sizeof(id), f); - - // order array - Order.WriteAsByte(f, MAX_ORDERS); - -// Song Patterns - - // number of patterns - id = MAX_PATTERNS; - fwrite(&id, 1, sizeof(id), f); - - // number of pattern name strings - id = m_nPatternNames; - fwrite(&id, 1, sizeof(id), f); - - // length of a pattern name string - id = MAX_PATTERNNAME; - fwrite(&id, 1, sizeof(id), f); - fwrite(&m_lpszPatternNames[0], 1, m_nPatternNames * MAX_PATTERNNAME, f); - - // modcommand data length - id = sizeof(MODCOMMAND_ORIGINAL); - fwrite(&id, 1, sizeof(id), f); - - // patterns data content - for(UINT npat=0; npat<MAX_PATTERNS; npat++){ - // pattern size (number of rows) - id = Patterns[npat] ? Patterns[npat].GetNumRows() : 0; - fwrite(&id, 1, sizeof(id), f); - // pattern data - if(Patterns[npat] && Patterns[npat].GetNumRows()) Patterns[npat].WriteITPdata(f); - //fwrite(Patterns[npat], 1, m_nChannels * Patterns[npat].GetNumRows() * sizeof(MODCOMMAND_ORIGINAL), f); - } - -// Song lonely (instrument-less) samples - - // Write original number of samples - id = m_nSamples; - fwrite(&id, 1, sizeof(id), f); - - BOOL sampleUsed[MAX_SAMPLES]; - memset(&sampleUsed,0,MAX_SAMPLES * sizeof(BOOL)); - - // Mark samples used in instruments - for(i=0; i<m_nInstruments; i++){ - if(Instruments[i+1]){ - MODINSTRUMENT *p = Instruments[i+1]; - for(j=0; j<128; j++) if(p->Keyboard[j]) sampleUsed[p->Keyboard[j]] = TRUE; - } - } - - // Count samples not used in any instrument - i = 0; - for(j=1; j<=m_nSamples; j++) if(!sampleUsed[j] && Samples[j].pSample) i++; - - id = i; - fwrite(&id, 1, sizeof(id), f); - - // Write samples not used in any instrument - ITSAMPLESTRUCT itss; - for(UINT nsmp=1; nsmp<=m_nSamples; nsmp++){ - if(!sampleUsed[nsmp] && Samples[nsmp].pSample){ - - MODSAMPLE *psmp = &Samples[nsmp]; - memset(&itss, 0, sizeof(itss)); - memcpy(itss.filename, psmp->filename, 12); - memcpy(itss.name, m_szNames[nsmp], 26); - - itss.id = 0x53504D49; - itss.gvl = (BYTE)psmp->nGlobalVol; - itss.flags = 0x00; - - if(psmp->uFlags & CHN_LOOP) itss.flags |= 0x10; - if(psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20; - if(psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40; - if(psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; - itss.C5Speed = psmp->nC5Speed; - if (!itss.C5Speed) itss.C5Speed = 8363; - itss.length = psmp->nLength; - itss.loopbegin = psmp->nLoopStart; - itss.loopend = psmp->nLoopEnd; - itss.susloopbegin = psmp->nSustainStart; - itss.susloopend = psmp->nSustainEnd; - itss.vol = psmp->nVolume >> 2; - itss.dfp = psmp->nPan >> 2; - itss.vit = autovibxm2it[psmp->nVibType & 7]; - itss.vis = min(psmp->nVibRate, 64); - itss.vid = min(psmp->nVibDepth, 32); - itss.vir = min(psmp->nVibSweep, 255); //(psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255; - if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80; - if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01; - UINT flags = RS_PCM8S; - - if(psmp->uFlags & CHN_STEREO){ - flags = RS_STPCM8S; - itss.flags |= 0x04; - } - if(psmp->uFlags & CHN_16BIT){ - itss.flags |= 0x02; - flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; - } - - id = nsmp; - fwrite(&id, 1, sizeof(id), f); - - itss.samplepointer = NULL; - fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); - - id = WriteSample(NULL, psmp, flags); - fwrite(&id, 1, sizeof(id), f); - WriteSample(f, psmp, flags); - } - } - -// Embed instruments' header [v1.01] - - if(m_dwSongFlags & SONG_ITPEMBEDIH){ - // embeded instrument header tag - __int32 code = 'EBIH'; - fwrite(&code, 1, sizeof(__int32), f); - - // instruments' header - for(i=0; i<m_nInstruments; i++){ - if(Instruments[i+1]) WriteInstrumentHeaderStruct(Instruments[i+1], f); - // write separator tag - code = 'SEP@'; - fwrite(&code, 1, sizeof(__int32), f); - } - } - - SaveExtendedSongProperties(f); - -// Close file - fclose(f); - return true; -} -// -! NEW_FEATURE#0023 - bool CSoundFile::SaveIT(LPCSTR lpszFileName, UINT nPacking) //------------------------------------------------------------- { Added: trunk/OpenMPT/soundlib/Load_itp.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_itp.cpp (rev 0) +++ trunk/OpenMPT/soundlib/Load_itp.cpp 2010-08-03 15:25:56 UTC (rev 669) @@ -0,0 +1,729 @@ +/* + * Load_itp.cpp + * ------------ + * Purpose: Load and save Impulse Tracker Project (ITP) files. + * Notes : Despite its name, ITP is not a format supported by Impulse Tracker. + * In fact, it's a format invented by the OpenMPT team to allow people to work + * with the IT format, but keeping the instrument files with big samples separate + * from the pattern data, to keep the work files small and handy. + * The current design of the format is quite flawed, though, so expect this to + * change in the (far?) future. + * Authors: OpenMPT Devs + * + */ + +#include "stdafx.h" +#include "Sndfile.h" +#include "IT_DEFS.H" +#include "../mptrack/mptrack.h" +#include "../mptrack/version.h" + + +#define ITP_VERSION 0x00000102 // v1.02 +#define ITP_FILE_ID 0x2e697470 // .itp ASCII + + +bool CSoundFile::ReadITProject(LPCBYTE lpStream, const DWORD dwMemLength) +//----------------------------------------------------------------------- +{ + UINT i,n,nsmp; + DWORD id,len,size; + DWORD streamPos = 0; + DWORD version; + + // Macro used to make sure that given amount of bytes can be read. + // Returns FALSE from this function if reading is not possible. + #define ASSERT_CAN_READ(x) \ + if( streamPos > dwMemLength || x > dwMemLength - streamPos ) return false; + + ASSERT_CAN_READ(12); + + // Check file ID + + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + if(id != ITP_FILE_ID) return false; + streamPos += sizeof(DWORD); + + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + version = id; + streamPos += sizeof(DWORD); + + m_nType = MOD_TYPE_IT; + + // Song name + + // name string length + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + len = id; + streamPos += sizeof(DWORD); + + // name string + ASSERT_CAN_READ(len); + if (len<=sizeof(m_szNames[0])) { + memcpy(m_szNames[0],lpStream+streamPos,len); + streamPos += len; + m_szNames[0][sizeof(m_szNames[0])-1] = '\0'; + } + else return false; + + // Song comments + + // comment string length + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + streamPos += sizeof(DWORD); + if(id > uint16_max) return false; + + // allocate and copy comment string + ASSERT_CAN_READ(id); + if(id > 0) + { + ReadMessage(lpStream + streamPos, id - 1, leCR); + } + streamPos += id; + + // Song global config + ASSERT_CAN_READ(5*4); + + // m_dwSongFlags + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_dwSongFlags = id; + streamPos += sizeof(DWORD); + + if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; + + // m_nDefaultGlobalVolume + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nDefaultGlobalVolume = id; + streamPos += sizeof(DWORD); + + // m_nSamplePreAmp + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nSamplePreAmp = id; + streamPos += sizeof(DWORD); + + // m_nDefaultSpeed + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nDefaultSpeed = id; + streamPos += sizeof(DWORD); + + // m_nDefaultTempo + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nDefaultTempo = id; + streamPos += sizeof(DWORD); + + // Song channels data + ASSERT_CAN_READ(2*4); + + // m_nChannels + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nChannels = (CHANNELINDEX)id; + streamPos += sizeof(DWORD); + if(m_nChannels > 127) return false; + + // channel name string length (=MAX_CHANNELNAME) + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + len = id; + streamPos += sizeof(DWORD); + if(len > MAX_CHANNELNAME) return false; + + // Channels' data + for(i=0; i<m_nChannels; i++){ + ASSERT_CAN_READ(3*4 + len); + + // ChnSettings[i].nPan + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + ChnSettings[i].nPan = id; + streamPos += sizeof(DWORD); + + // ChnSettings[i].dwFlags + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + ChnSettings[i].dwFlags = id; + streamPos += sizeof(DWORD); + + // ChnSettings[i].nVolume + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + ChnSettings[i].nVolume = id; + streamPos += sizeof(DWORD); + + // ChnSettings[i].szName + memcpy(&ChnSettings[i].szName[0],lpStream+streamPos,len); + SetNullTerminator(ChnSettings[i].szName); + streamPos += len; + } + + // Song mix plugins + // size of mix plugins data + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + streamPos += sizeof(DWORD); + + // mix plugins + ASSERT_CAN_READ(id); + streamPos += LoadMixPlugins(lpStream+streamPos, id); + + // Song midi config + + // midi cfg data length + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + streamPos += sizeof(DWORD); + + // midi cfg + ASSERT_CAN_READ(id); + if (id<=sizeof(m_MidiCfg)) { + memcpy(&m_MidiCfg,lpStream+streamPos,id); + streamPos += id; + } + + // Song Instruments + + // m_nInstruments + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nInstruments = (INSTRUMENTINDEX)id; + if(m_nInstruments > MAX_INSTRUMENTS) return false; + streamPos += sizeof(DWORD); + + // path string length (=_MAX_PATH) + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + len = id; + if(len > _MAX_PATH) return false; + streamPos += sizeof(DWORD); + + // instruments' paths + for(i=0; i<m_nInstruments; i++){ + ASSERT_CAN_READ(len); + memcpy(&m_szInstrumentPath[i][0],lpStream+streamPos,len); + SetNullTerminator(m_szInstrumentPath[i]); + streamPos += len; + } + + // Song Orders + + // size of order array (=MAX_ORDERS) + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + size = id; + if(size > MAX_ORDERS) return false; + streamPos += sizeof(DWORD); + + // order data + ASSERT_CAN_READ(size); + Order.ReadAsByte(lpStream+streamPos, size, dwMemLength-streamPos); + streamPos += size; + + + + // Song Patterns + + ASSERT_CAN_READ(3*4); + // number of patterns (=MAX_PATTERNS) + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + size = id; + streamPos += sizeof(DWORD); + if(size > MAX_PATTERNS) return false; + + // m_nPatternNames + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + m_nPatternNames = id; + streamPos += sizeof(DWORD); + + // pattern name string length (=MAX_PATTERNNAME) + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + len = id; + streamPos += sizeof(DWORD); + + // m_lpszPatternNames + if (len<=MAX_PATTERNNAME && m_nPatternNames<=MAX_PATTERNS) + { + m_lpszPatternNames = new char[m_nPatternNames * len]; + ASSERT_CAN_READ(m_nPatternNames * len); + memcpy(&m_lpszPatternNames[0],lpStream+streamPos,m_nPatternNames * len); + } + else return false; + + streamPos += m_nPatternNames * len; + + // modcommand data length + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + n = id; + if(n != 6) return false; + streamPos += sizeof(DWORD); + + for(PATTERNINDEX npat=0; npat<size; npat++) + { + // Free pattern if not empty + if(Patterns[npat]) { FreePattern(Patterns[npat]); Patterns[npat] = NULL; } + + // Patterns[npat].GetNumRows() + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + if(id > MAX_PATTERN_ROWS) return false; + Patterns[npat].Resize(id, false); + streamPos += sizeof(DWORD); + + // Try to allocate & read only sized patterns + if(Patterns[npat].GetNumRows()){ + + // Allocate pattern + if(Patterns.Insert(npat, Patterns[npat].GetNumRows())){ + streamPos += m_nChannels * Patterns[npat].GetNumRows() * n; + continue; + } + + // Pattern data + long datasize = m_nChannels * Patterns[npat].GetNumRows() * n; + //if (streamPos+datasize<=dwMemLength) { + if(Patterns[npat].ReadITPdata(lpStream, streamPos, datasize, dwMemLength)) + { + ErrorBox(IDS_ERR_FILEOPEN, NULL); + return false; + } + //memcpy(Patterns[npat],lpStream+streamPos,datasize); + //streamPos += datasize; + //} + } + } + + // Load embeded samples + + ITSAMPLESTRUCT pis; + + // Read original number of samples + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + if(id > MAX_SAMPLES) return false; + m_nSamples = (SAMPLEINDEX)id; + streamPos += sizeof(DWORD); + + // Read number of embeded samples + ASSERT_CAN_READ(4); + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + if(id > MAX_SAMPLES) return false; + n = id; + streamPos += sizeof(DWORD); + + // Read samples + for(i=0; i<n; i++){ + + ASSERT_CAN_READ(4 + sizeof(ITSAMPLESTRUCT) + 4); + + // Sample id number + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + nsmp = id; + streamPos += sizeof(DWORD); + + if(nsmp < 1 || nsmp >= MAX_SAMPLES) + return false; + + // Sample struct + memcpy(&pis,lpStream+streamPos,sizeof(ITSAMPLESTRUCT)); + streamPos += sizeof(ITSAMPLESTRUCT); + + // Sample length + memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + len = id; + streamPos += sizeof(DWORD); + if(streamPos >= dwMemLength || len > dwMemLength - streamPos) return false; + + // Copy sample struct data + if(pis.id == 0x53504D49) + { + MODSAMPLE *pSmp = &Samples[nsmp]; + memcpy(pSmp->filename, pis.filename, 12); + pSmp->uFlags = 0; + pSmp->nLength = 0; + pSmp->nLoopStart = pis.loopbegin; + pSmp->nLoopEnd = pis.loopend; + pSmp->nSustainStart = pis.susloopbegin; + pSmp->nSustainEnd = pis.susloopend; + pSmp->nC5Speed = pis.C5Speed; + if(!pSmp->nC5Speed) pSmp->nC5Speed = 8363; + if(pis.C5Speed < 256) pSmp->nC5Speed = 256; + pSmp->nVolume = pis.vol << 2; + if(pSmp->nVolume > 256) pSmp->nVolume = 256; + pSmp->nGlobalVol = pis.gvl; + if(pSmp->nGlobalVol > 64) pSmp->nGlobalVol = 64; + if(pis.flags & 0x10) pSmp->uFlags |= CHN_LOOP; + if(pis.flags & 0x20) pSmp->uFlags |= CHN_SUSTAINLOOP; + if(pis.flags & 0x40) pSmp->uFlags |= CHN_PINGPONGLOOP; + if(pis.flags & 0x80) pSmp->uFlags |= CHN_PINGPONGSUSTAIN; + pSmp->nPan = (pis.dfp & 0x7F) << 2; + if(pSmp->nPan > 256) pSmp->nPan = 256; + if(pis.dfp & 0x80) pSmp->uFlags |= CHN_PANNING; + pSmp->nVibType = autovibit2xm[pis.vit & 7]; + pSmp->nVibRate = pis.vis; + pSmp->nVibDepth = pis.vid & 0x7F; + pSmp->nVibSweep = pis.vir; + if(pis.length){ + pSmp->nLength = pis.length; + if (pSmp->nLength > MAX_SAMPLE_LENGTH) pSmp->nLength = MAX_SAMPLE_LENGTH; + UINT flags = (pis.cvt & 1) ? RS_PCM8S : RS_PCM8U; + if (pis.flags & 2){ + flags += 5; + if (pis.flags & 4) flags |= RSF_STEREO; + pSmp->uFlags |= CHN_16BIT; + } + else{ + if (pis.flags & 4) flags |= RSF_STEREO; + } + // Read sample data + ReadSample(&Samples[nsmp], flags, (LPSTR)(lpStream+streamPos), len); + streamPos += len; + memcpy(m_szNames[nsmp], pis.name, 26); + } + } + } + + // Load instruments + + CMappedFile f; + LPBYTE lpFile; + + for(INSTRUMENTINDEX i = 0; i < m_nInstruments; i++) + { + + if(m_szInstrumentPath[i][0] == '\0' || !f.Open(m_szInstrumentPath[i])) continue; + + len = f.GetLength(); + lpFile = f.Lock(len); + if(!lpFile) { f.Close(); continue; } + + ReadInstrumentFromFile(i+1, lpFile, len); + f.Unlock(); + f.Close(); + } + + // Extra info data + + __int32 fcode = 0; + LPCBYTE ptr = lpStream + min(streamPos, dwMemLength); + + if (streamPos <= dwMemLength - 4) { + fcode = (*((__int32 *)ptr)); + } + + // Embed instruments' header [v1.01] + if(version >= 0x00000101 && m_dwSongFlags & SONG_ITPEMBEDIH && fcode == 'EBIH'){ + // jump embeded instrument header tag + ptr += sizeof(__int32); + + // set first instrument's header as current + i = 1; + + // parse file + while( uintptr_t(ptr - lpStream) <= dwMemLength - 4 && i <= m_nInstruments ) + { + + fcode = (*((__int32 *)ptr)); // read field code + + switch( fcode ) + { + case 'MPTS': goto mpts; //:) // reached end of instrument headers + case 'SEP@': case 'MPTX': + ptr += sizeof(__int32); // jump code + i++; // switch to next instrument + break; + + default: + ptr += sizeof(__int32); // jump field code + ReadExtendedInstrumentProperty(Instruments[i], fcode, ptr, lpStream + dwMemLength); + break; + } + } + } + + //HACK: if we fail on i <= m_nInstruments above, arrive here without having set fcode as appropriate, + // hence the code duplication. + if ( (uintptr_t)(ptr - lpStream) <= dwMemLength - 4 ) + { + fcode = (*((__int32 *)ptr)); + } + + // Song extensions +mpts: + if( fcode == 'MPTS' ) + LoadExtendedSongProperties(MOD_TYPE_IT, ptr, lpStream, dwMemLength); + + m_nMaxPeriod = 0xF000; + m_nMinPeriod = 8; + + if(m_dwLastSavedWithVersion < MAKE_VERSION_NUMERIC(1, 17, 2, 50)) + { + SetModFlag(MSF_COMPATIBLE_PLAY, false); + SetModFlag(MSF_MIDICC_BUGEMULATION, true); + SetModFlag(MSF_OLDVOLSWING, true); + } + + return true; + + #undef ASSERT_CAN_READ +} + + +#ifndef MODPLUG_NO_FILESAVE + +bool CSoundFile::SaveITProject(LPCSTR lpszFileName) +//------------------------------------------------- +{ + // Check song type + + if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; + + UINT i,j = 0; + for(i = 0 ; i < m_nInstruments ; i++) { if(m_szInstrumentPath[i][0] != '\0' || !Instruments[i+1]) j++; } + if(m_nInstruments && j != m_nInstruments) return false; + + // Open file + + FILE *f; + + if((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return false; + + + // File ID + + DWORD id = ITP_FILE_ID; + fwrite(&id, 1, sizeof(id), f); + + id = ITP_VERSION; + fwrite(&id, 1, sizeof(id), f); + + // Song name + + // name string length + id = 27; + fwrite(&id, 1, sizeof(id), f); + + // song name + fwrite(&m_szNames[0], 1, 27, f); + + // Song comments + + // comment string length + id = m_lpszSongComments ? strlen(m_lpszSongComments)+1 : 0; + fwrite(&id, 1, sizeof(id), f); + + // comment string + if(m_lpszSongComments) fwrite(&m_lpszSongComments[0], 1, strlen(m_lpszSongComments)+1, f); + + // Song global config + + id = m_dwSongFlags; + fwrite(&id, 1, sizeof(id), f); + id = m_nDefaultGlobalVolume; + fwrite(&id, 1, sizeof(id), f); + id = m_nSamplePreAmp; + fwrite(&id, 1, sizeof(id), f); + id = m_nDefaultSpeed; + fwrite(&id, 1, sizeof(id), f); + id = m_nDefaultTempo; + fwrite(&id, 1, sizeof(id), f); + + // Song channels data + + // number of channels + id = m_nChannels; + fwrite(&id, 1, sizeof(id), f); + + // channel name string length + id = MAX_CHANNELNAME; + fwrite(&id, 1, sizeof(id), f); + + // channel config data + for(i=0; i<m_nChannels; i++){ + id = ChnSettings[i].nPan; + fwrite(&id, 1, sizeof(id), f); + id = ChnSettings[i].dwFlags; + fwrite(&id, 1, sizeof(id), f); + id = ChnSettings[i].nVolume; + fwrite(&id, 1, sizeof(id), f); + fwrite(&ChnSettings[i].szName[0], 1, MAX_CHANNELNAME, f); + } + + // Song mix plugins + + // mix plugins data length + id = SaveMixPlugins(NULL, TRUE); + fwrite(&id, 1, sizeof(id), f); + + // mix plugins data + SaveMixPlugins(f, FALSE); + + // Song midi config + + // midi cfg data length + id = sizeof(MODMIDICFG); + fwrite(&id, 1, sizeof(id), f); + + // midi cfg + fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); + + // Song Instruments + + // number of instruments + id = m_nInstruments; + fwrite(&id, 1, sizeof(id), f); + + // path name string length + id = _MAX_PATH; + fwrite(&id, 1, sizeof(id), f); + + // instruments' path + for(i=0; i<m_nInstruments; i++) fwrite(&m_szInstrumentPath[i][0], 1, _MAX_PATH, f); + + // Song Orders + + // order array size + id = Order.size(); + fwrite(&id, 1, sizeof(id), f); + + // order array + Order.WriteAsByte(f, MAX_ORDERS); + + // Song Patterns + + // number of patterns + id = MAX_PATTERNS; + fwrite(&id, 1, sizeof(id), f); + + // number of pattern name strings + id = m_nPatternNames; + fwrite(&id, 1, sizeof(id), f); + + // length of a pattern name string + id = MAX_PATTERNNAME; + fwrite(&id, 1, sizeof(id), f); + fwrite(&m_lpszPatternNames[0], 1, m_nPatternNames * MAX_PATTERNNAME, f); + + // modcommand data length + id = sizeof(MODCOMMAND_ORIGINAL); + fwrite(&id, 1, sizeof(id), f); + + // patterns data content + for(UINT npat=0; npat<MAX_PATTERNS; npat++){ + // pattern size (number of rows) + id = Patterns[npat] ? Patterns[npat].GetNumRows() : 0; + fwrite(&id, 1, sizeof(id), f); + // pattern data + if(Patterns[npat] && Patterns[npat].GetNumRows()) Patterns[npat].WriteITPdata(f); + //fwrite(Patterns[npat], 1, m_nChannels * Patterns[npat].GetNumRows() * sizeof(MODCOMMAND_ORIGINAL), f); + } + + // Song lonely (instrument-less) samples + + // Write original number of samples + id = m_nSamples; + fwrite(&id, 1, sizeof(id), f); + + vector<bool> sampleUsed(m_nSamples, false); + + // Mark samples used in instruments + for(i=0; i<m_nInstruments; i++) + { + if(Instruments[i + 1] != nullptr) + { + MODINSTRUMENT *p = Instruments[i + 1]; + for(j = 0; j < 128; j++) + { + if(p->Keyboard[j] > 0 && p->Keyboard[j] <= m_nSamples) + sampleUsed[p->Keyboard[j] - 1] = true; + } + } + } + + // Count samples not used in any instrument + i = 0; + for(j = 1; j <= m_nSamples; j++) + if(!sampleUsed[j - 1] && Samples[j].pSample) i++; + + id = i; + fwrite(&id, 1, sizeof(id), f); + + // Write samples not used in any instrument (help, this looks like duplicate code!) + ITSAMPLESTRUCT itss; + for(UINT nsmp=1; nsmp<=m_nSamples; nsmp++) + { + if(!sampleUsed[nsmp - 1] && Samples[nsmp].pSample) + { + + MODSAMPLE *psmp = &Samples[nsmp]; + memset(&itss, 0, sizeof(itss)); + memcpy(itss.filename, psmp->filename, 12); + memcpy(itss.name, m_szNames[nsmp], 26); + + itss.id = 0x53504D49; + itss.gvl = (BYTE)psmp->nGlobalVol; + itss.flags = 0x00; + + if(psmp->uFlags & CHN_LOOP) itss.flags |= 0x10; + if(psmp->uFlags & CHN_SUSTAINLOOP) itss.flags |= 0x20; + if(psmp->uFlags & CHN_PINGPONGLOOP) itss.flags |= 0x40; + if(psmp->uFlags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; + itss.C5Speed = psmp->nC5Speed; + if (!itss.C5Speed) itss.C5Speed = 8363; + itss.length = psmp->nLength; + itss.loopbegin = psmp->nLoopStart; + itss.loopend = psmp->nLoopEnd; + itss.susloopbegin = psmp->nSustainStart; + itss.susloopend = psmp->nSustainEnd; + itss.vol = (BYTE)(psmp->nVolume >> 2); + itss.dfp = (BYTE)(psmp->nPan >> 2); + itss.vit = autovibxm2it[psmp->nVibType & 7]; + itss.vis = min(psmp->nVibRate, 64); + itss.vid = min(psmp->nVibDepth, 32); + itss.vir = min(psmp->nVibSweep, 255); //(psmp->nVibSweep < 64) ? psmp->nVibSweep * 4 : 255; + if (psmp->uFlags & CHN_PANNING) itss.dfp |= 0x80; + if ((psmp->pSample) && (psmp->nLength)) itss.cvt = 0x01; + UINT flags = RS_PCM8S; + + if(psmp->uFlags & CHN_STEREO) + { + flags = RS_STPCM8S; + itss.flags |= 0x04; + } + if(psmp->uFlags & CHN_16BIT) + { + itss.flags |= 0x02; + flags = (psmp->uFlags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; + } + + id = nsmp; + fwrite(&id, 1, sizeof(id), f); + + itss.samplepointer = NULL; + fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); + + id = WriteSample(NULL, psmp, flags); + fwrite(&id, 1, sizeof(id), f); + WriteSample(f, psmp, flags); + } + } + + // Embed instruments' header [v1.01] + + if(m_dwSongFlags & SONG_ITPEMBEDIH){ + // embeded instrument header tag + __int32 code = 'EBIH'; + fwrite(&code, 1, sizeof(__int32), f); + + // instruments' header + for(i=0; i<m_nInstruments; i++){ + if(Instruments[i+1]) WriteInstrumentHeaderStruct(Instruments[i+1], f); + // write separator tag + code = 'SEP@'; + fwrite(&code, 1, sizeof(__int32), f); + } + } + + SaveExtendedSongProperties(f); + + // Close file + fclose(f); + return true; +} + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-08-03 22:28:40
|
Revision: 671 http://modplug.svn.sourceforge.net/modplug/?rev=671&view=rev Author: saga-games Date: 2010-08-03 22:28:34 +0000 (Tue, 03 Aug 2010) Log Message: ----------- [Ref] Rewrote pattern/envelope paste code a bit using sscanf. At least pattern pasting is more fool-proof now. Modified Paths: -------------- trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_ins.cpp trunk/OpenMPT/soundlib/Snd_defs.h Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2010-08-03 17:34:45 UTC (rev 670) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2010-08-03 22:28:34 UTC (rev 671) @@ -1027,13 +1027,13 @@ // Clipboard format: -// Hdr: "ModPlug Tracker S3M\n" +// Hdr: "ModPlug Tracker S3M\r\n" // Full: '|C#401v64A06' // Reset: '|...........' // Empty: '| ' // End of row: '\n' -static LPCSTR lpszClipboardPatternHdr = "ModPlug Tracker %3s\x0D\x0A"; +static LPCSTR lpszClipboardPatternHdr = "ModPlug Tracker %3s\r\n"; bool CModDoc::CopyPattern(PATTERNINDEX nPattern, DWORD dwBeginSel, DWORD dwEndSel) //-------------------------------------------------------------------------------- @@ -1168,8 +1168,8 @@ p[9] = p[10] = p[11] = ' '; } } - *p++ = 0x0D; - *p++ = 0x0A; + *p++ = '\r'; + *p++ = '\n'; } *p = 0; } @@ -1197,70 +1197,69 @@ { const TEMPO spdmax = m_SndFile.GetModSpecifications().speedMax; const DWORD dwMemSize = GlobalSize(hCpy); + CHANNELINDEX ncol = (dwBeginSel & 0xFFFF) >> 3, col; + const ROWINDEX startRow = (ROWINDEX)(dwBeginSel >> 16); + ROWINDEX nrow = startRow; + bool bOk = false; + bool bPrepareUndo = true; // prepare pattern for undo next time + bool bFirstUndo = true; // for chaining undos (see overflow paste) + MODTYPE origFormat = MOD_TYPE_IT; // paste format + size_t pos, startPos = 0; MODCOMMAND *m = m_SndFile.Patterns[nPattern]; - UINT nrow = dwBeginSel >> 16; - UINT ncol = (dwBeginSel & 0xFFFF) >> 3; - UINT col; - bool bS3MCommands = false, bOk = false; - bool bPrepareUndo = true, bFirstUndo = true; - MODTYPE origFormat = MOD_TYPE_IT; - UINT len = 0, startLen; const bool doOverflowPaste = (CMainFrame::m_dwPatternSetup & PATTERN_OVERFLOWPASTE) && (pasteMode != pm_pasteflood) && (pasteMode != pm_pushforwardpaste); const bool doITStyleMix = (pasteMode == pm_mixpaste_it); const bool doMixPaste = ((pasteMode == pm_mixpaste) || doITStyleMix); ORDERINDEX oCurrentOrder; //jojo.echopaste - ROWINDEX rTemp, startRow; + ROWINDEX rTemp; PATTERNINDEX pTemp; GetEditPosition(rTemp, pTemp, oCurrentOrder); - if ((nrow >= m_SndFile.Patterns[nPattern].GetNumRows()) || (ncol >= m_SndFile.m_nChannels)) goto PasteDone; + if ((nrow >= m_SndFile.Patterns[nPattern].GetNumRows()) || (ncol >= m_SndFile.GetNumChannels())) goto PasteDone; m += nrow * m_SndFile.m_nChannels; - + // Search for signature - for (;;) + for (pos = startPos; p[pos] != 0 && pos < dwMemSize; pos++) { - if (len + 11 >= dwMemSize) goto PasteDone; - char c = p[len++]; - if (!c) goto PasteDone; - if ((c == 0x0D) && (len > 3)) + CHAR szFormat[4]; // adjust this if the "%3s" part in the format string changes. + if(sscanf(p + pos, lpszClipboardPatternHdr, szFormat) > 0) { - if(p[len - 3] == 'I') origFormat = MOD_TYPE_IT; - if(p[len - 3] == 'P') origFormat = MOD_TYPE_MPT; - if(p[len - 4] == 'S') origFormat = MOD_TYPE_S3M; - if(p[len - 3] == 'X') origFormat = MOD_TYPE_XM; - if(p[len - 3] == 'O') origFormat = MOD_TYPE_MOD; + if(!strcmp(szFormat, "S3M")) origFormat = MOD_TYPE_S3M; + if(!strcmp(szFormat, "XM")) origFormat = MOD_TYPE_XM; + if(!strcmp(szFormat, "IT")) origFormat = MOD_TYPE_IT; + if(!strcmp(szFormat, "MPT")) origFormat = MOD_TYPE_MPT; + if(!strcmp(szFormat, "MOD")) origFormat = MOD_TYPE_MOD; + startPos = pos; // start reading patterns from here break; } } - bS3MCommands = (origFormat & (MOD_TYPE_IT|MOD_TYPE_MPT|MOD_TYPE_S3M)) != 0 ? true : false; - bOk = true; - startLen = len; - startRow = nrow; + const bool bS3MCommands = (origFormat & (MOD_TYPE_IT|MOD_TYPE_MPT|MOD_TYPE_S3M)) != 0 ? true : false; + pos = startPos; while ((nrow < m_SndFile.Patterns[nPattern].GetNumRows())) { // Search for column separator or end of paste data - while ((len + 11 >= dwMemSize) || p[len] != '|') + while ((pos + 11 >= dwMemSize) || p[pos] != '|') { - if (len + 11 >= dwMemSize || !p[len]) + if (pos + 11 >= dwMemSize || !p[pos]) { if((pasteMode == pm_pasteflood) && (nrow != startRow)) // prevent infinite loop with malformed clipboard data - len = startLen; // paste from beginning + pos = startPos; // paste from beginning else goto PasteDone; } else { - len++; + pos++; } } + bOk = true; col = ncol; // Paste columns - while ((p[len] == '|') && (len + 11 < dwMemSize)) + while ((p[pos] == '|') && (pos + 11 < dwMemSize)) { - LPSTR s = p+len+1; + LPSTR s = p+pos+1; // Check valid paste condition. Paste will be skipped if // -col is not a valid channelindex or @@ -1434,7 +1433,7 @@ m_SndFile.ConvertCommand(&(m[col]), origFormat, m_SndFile.m_nType); } - len += 12; + pos += 12; col++; } // Next row @@ -1477,8 +1476,8 @@ ///////////////////////////////////////////////////////////////////////////////////////// // Copy/Paste envelope -static LPCSTR pszEnvHdr = "Modplug Tracker Envelope\x0D\x0A"; -static LPCSTR pszEnvFmt = "%d,%d,%d,%d,%d,%d,%d,%d\x0D\x0A"; +static LPCSTR pszEnvHdr = "Modplug Tracker Envelope\r\n"; +static LPCSTR pszEnvFmt = "%d,%d,%d,%d,%d,%d,%d,%d\r\n"; bool CModDoc::CopyEnvelope(UINT nIns, enmEnvelopeTypes nEnv) //---------------------------------------------------------- @@ -1492,6 +1491,7 @@ if ((nIns < 1) || (nIns > m_SndFile.m_nInstruments) || (!m_SndFile.Instruments[nIns]) || (!pMainFrm)) return false; BeginWaitCursor(); pIns = m_SndFile.Instruments[nIns]; + if(pIns == nullptr) return false; INSTRUMENTENVELOPE *pEnv = nullptr; @@ -1513,12 +1513,12 @@ for (UINT i = 0; i < pEnv->nNodes; i++) { if (strlen(s) >= sizeof(s)-32) break; - wsprintf(s+strlen(s), "%d,%d\x0D\x0A", pEnv->Ticks[i], pEnv->Values[i]); + wsprintf(s+strlen(s), "%d,%d\r\n", pEnv->Ticks[i], pEnv->Values[i]); } //Writing release node if(strlen(s) < sizeof(s) - 32) - wsprintf(s+strlen(s), "%u\x0D\x0A", pEnv->nReleaseNode); + wsprintf(s+strlen(s), "%u\r\n", pEnv->nReleaseNode); dwMemSize = strlen(s)+1; if ((pMainFrm->OpenClipboard()) && ((hCpy = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, dwMemSize))!=NULL)) @@ -1554,28 +1554,13 @@ MODINSTRUMENT *pIns = m_SndFile.Instruments[nIns]; INSTRUMENTENVELOPE *pEnv = nullptr; - UINT susBegin=0, susEnd=0, loopBegin=0, loopEnd=0, bSus=0, bLoop=0, bCarry=0, nPoints=0, releaseNode = ENV_RELEASE_NODE_UNSET; + UINT susBegin = 0, susEnd = 0, loopBegin = 0, loopEnd = 0, bSus = 0, bLoop = 0, bCarry = 0, nPoints = 0, releaseNode = ENV_RELEASE_NODE_UNSET; DWORD dwMemSize = GlobalSize(hCpy), dwPos = strlen(pszEnvHdr); - if ((dwMemSize > dwPos) && (!_strnicmp(p, pszEnvHdr, dwPos-2))) + if ((dwMemSize > dwPos) && (!_strnicmp(p, pszEnvHdr, dwPos - 2))) { - for (UINT h=0; h<8; h++) - { - while ((dwPos < dwMemSize) && ((p[dwPos] < '0') || (p[dwPos] > '9'))) dwPos++; - if (dwPos >= dwMemSize) break; - int n = atoi(p+dwPos); - switch(h) - { - case 0: nPoints = n; break; - case 1: susBegin = n; break; - case 2: susEnd = n; break; - case 3: loopBegin = n; break; - case 4: loopEnd = n; break; - case 5: bSus = n; break; - case 6: bLoop = n; break; - case 7: bCarry = n; break; - } - while ((dwPos < dwMemSize) && ((p[dwPos] >= '0') && (p[dwPos] <= '9'))) dwPos++; - } + sscanf(p + dwPos, pszEnvFmt, &nPoints, &susBegin, &susEnd, &loopBegin, &loopEnd, &bSus, &bLoop, &bCarry); + while ((dwPos < dwMemSize) && (p[dwPos] != '\r') && (p[dwPos] != '\n')) dwPos++; + nPoints = min(nPoints, m_SndFile.GetModSpecifications().envelopePointsMax); if (susEnd >= nPoints) susEnd = 0; if (susBegin > susEnd) susBegin = susEnd; @@ -1612,11 +1597,11 @@ while ((dwPos < dwMemSize) && ((p[dwPos] < '0') || (p[dwPos] > '9'))) dwPos++; if (dwPos >= dwMemSize) break; int n2 = atoi(p+dwPos); - if ((n1 < oldn) || (n1 > 0x3FFF)) n1 = oldn+1; + if ((n1 < oldn) || (n1 > ENVELOPE_MAX_LENGTH)) n1 = oldn + 1; pEnv->Ticks[i] = (WORD)n1; pEnv->Values[i] = (BYTE)n2; oldn = n1; - while ((dwPos < dwMemSize) && (p[dwPos] != 0x0D)) dwPos++; + while ((dwPos < dwMemSize) && (p[dwPos] != '\r') && (p[dwPos] != '\n')) dwPos++; if (dwPos >= dwMemSize) break; } Modified: trunk/OpenMPT/mptrack/View_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_ins.cpp 2010-08-03 17:34:45 UTC (rev 670) +++ trunk/OpenMPT/mptrack/View_ins.cpp 2010-08-03 22:28:34 UTC (rev 671) @@ -260,7 +260,7 @@ { int mintick = (nPoint) ? envelope->Ticks[nPoint-1] : 0; int maxtick = envelope->Ticks[nPoint+1]; - if (nPoint + 1 == (int)envelope->nNodes) maxtick = 16383; + if (nPoint + 1 == (int)envelope->nNodes) maxtick = ENVELOPE_MAX_LENGTH; if (nTick < mintick) nTick = mintick; if (nTick > maxtick) nTick = maxtick; if (nTick != envelope->Ticks[nPoint]) @@ -767,7 +767,8 @@ } - if (windowResized || m_bGridForceRedraw || (cachedScrollPos != m_GridScrollPos) || (speed != (UINT)m_GridSpeed)) { + if (windowResized || m_bGridForceRedraw || (cachedScrollPos != m_GridScrollPos) || (speed != (UINT)m_GridSpeed)) + { m_GridSpeed = speed; m_GridScrollPos = cachedScrollPos; Modified: trunk/OpenMPT/soundlib/Snd_defs.h =================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h 2010-08-03 17:34:45 UTC (rev 670) +++ trunk/OpenMPT/soundlib/Snd_defs.h 2010-08-03 22:28:34 UTC (rev 671) @@ -172,9 +172,10 @@ #define ENV_FILTER 0x10 // filter env enabled (this has to be combined with ENV_ENABLED in the pitch envelope's flags) // Envelope value boundaries -#define ENVELOPE_MIN 0 -#define ENVELOPE_MID 32 -#define ENVELOPE_MAX 64 +#define ENVELOPE_MIN 0 // vertical min value of a point +#define ENVELOPE_MID 32 // vertical middle line +#define ENVELOPE_MAX 64 // vertical max value of a point +#define ENVELOPE_MAX_LENGTH 0x3FFF // max envelope length in ticks. note: this value seems to be conservatively low... // Flags of 'dF..' datafield in extended instrument properties. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2010-08-05 11:44:18
|
Revision: 676 http://modplug.svn.sourceforge.net/modplug/?rev=676&view=rev Author: saga-games Date: 2010-08-05 11:44:10 +0000 (Thu, 05 Aug 2010) Log Message: ----------- [Ref] Moved ASSERT_CAN_READ macro to a new file, Loaders.h. Functions and macros that are common between loaders should be placed here in the future. Modified Paths: -------------- trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj 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_gdm.cpp trunk/OpenMPT/soundlib/Load_imf.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_itp.cpp trunk/OpenMPT/soundlib/Load_mdl.cpp trunk/OpenMPT/soundlib/Load_med.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/Load_mo3.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/load_j2b.cpp Added Paths: ----------- trunk/OpenMPT/soundlib/Loaders.h Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2010-08-05 11:44:10 UTC (rev 676) @@ -795,6 +795,9 @@ RelativePath=".\KeyConfigDlg.h"> </File> <File + RelativePath="..\soundlib\Loaders.h"> + </File> + <File RelativePath=".\mainbar.h"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2010-08-05 11:44:10 UTC (rev 676) @@ -1055,6 +1055,10 @@ > </File> <File + RelativePath="..\soundlib\Loaders.h" + > + </File> + <File RelativePath=".\mainbar.h" > </File> Modified: trunk/OpenMPT/soundlib/LOAD_AMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/LOAD_AMF.CPP 2010-08-05 11:44:10 UTC (rev 676) @@ -17,7 +17,7 @@ // /////////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" //#define AMFLOG Modified: trunk/OpenMPT/soundlib/LOAD_DBM.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DBM.CPP 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/LOAD_DBM.CPP 2010-08-05 11:44:10 UTC (rev 676) @@ -17,7 +17,7 @@ /////////////////////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #define DBM_FILE_MAGIC 0x304d4244 #define DBM_ID_NAME 0x454d414e Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2010-08-05 11:44:10 UTC (rev 676) @@ -11,7 +11,7 @@ // DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) // /////////////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" //#define DMFLOG Modified: trunk/OpenMPT/soundlib/LOAD_DSM.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DSM.CPP 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/LOAD_DSM.CPP 2010-08-05 11:44:10 UTC (rev 676) @@ -11,7 +11,7 @@ // DSIK Internal Format (DSM) module loader // ////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma pack(1) Modified: trunk/OpenMPT/soundlib/Load_669.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_669.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_669.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -13,7 +13,7 @@ //////////////////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -17,7 +17,7 @@ // AMS (Extreme's Tracker) module loader // ////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/soundlib/Load_far.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_far.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_far.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -11,7 +11,7 @@ // Farandole (FAR) module loader // //////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/soundlib/Load_gdm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_gdm.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -13,7 +13,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #ifdef MODPLUG_TRACKER #include "../mptrack/moddoc.h" #endif // MODPLUG_TRACKER Modified: trunk/OpenMPT/soundlib/Load_imf.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_imf.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_imf.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -7,7 +7,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #ifdef MODPLUG_TRACKER #include "../mptrack/moddoc.h" #endif // MODPLUG_TRACKER @@ -266,9 +266,6 @@ bool CSoundFile::ReadIMF(const LPCBYTE lpStream, const DWORD dwMemLength) //----------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - DWORD dwMemPos = 0; IMFHEADER hdr; MODSAMPLE *pSample = Samples + 1; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -8,8 +8,8 @@ */ #include "stdafx.h" -#include "sndfile.h" -#include "it_defs.h" +#include "Loaders.h" +#include "IT_DEFS.H" #include "tuningcollection.h" #include "../mptrack/moddoc.h" #include "../mptrack/serialization_utils.h" Modified: trunk/OpenMPT/soundlib/Load_itp.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_itp.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_itp.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -13,7 +13,7 @@ */ #include "stdafx.h" -#include "Sndfile.h" +#include "Loaders.h" #include "IT_DEFS.H" #include "../mptrack/mptrack.h" #include "../mptrack/version.h" @@ -28,40 +28,35 @@ { UINT i,n,nsmp; DWORD id,len,size; - DWORD streamPos = 0; + DWORD dwMemPos = 0; DWORD version; - // Macro used to make sure that given amount of bytes can be read. - // Returns FALSE from this function if reading is not possible. - #define ASSERT_CAN_READ(x) \ - if( streamPos > dwMemLength || x > dwMemLength - streamPos ) return false; - ASSERT_CAN_READ(12); // Check file ID - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); if(id != ITP_FILE_ID) return false; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); version = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); m_nType = MOD_TYPE_IT; // Song name // name string length - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); len = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // name string ASSERT_CAN_READ(len); if (len<=sizeof(m_szNames[0])) { - memcpy(m_szNames[0],lpStream+streamPos,len); - streamPos += len; + memcpy(m_szNames[0],lpStream+dwMemPos,len); + dwMemPos += len; m_szNames[0][sizeof(m_szNames[0])-1] = '\0'; } else return false; @@ -70,61 +65,61 @@ // comment string length ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - streamPos += sizeof(DWORD); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); + dwMemPos += sizeof(DWORD); if(id > uint16_max) return false; // allocate and copy comment string ASSERT_CAN_READ(id); if(id > 0) { - ReadMessage(lpStream + streamPos, id - 1, leCR); + ReadMessage(lpStream + dwMemPos, id - 1, leCR); } - streamPos += id; + dwMemPos += id; // Song global config ASSERT_CAN_READ(5*4); // m_dwSongFlags - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_dwSongFlags = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; // m_nDefaultGlobalVolume - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nDefaultGlobalVolume = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // m_nSamplePreAmp - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nSamplePreAmp = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // m_nDefaultSpeed - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nDefaultSpeed = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // m_nDefaultTempo - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nDefaultTempo = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // Song channels data ASSERT_CAN_READ(2*4); // m_nChannels - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nChannels = (CHANNELINDEX)id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); if(m_nChannels > 127) return false; // channel name string length (=MAX_CHANNELNAME) - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); len = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); if(len > MAX_CHANNELNAME) return false; // Channels' data @@ -132,87 +127,87 @@ ASSERT_CAN_READ(3*4 + len); // ChnSettings[i].nPan - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); ChnSettings[i].nPan = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // ChnSettings[i].dwFlags - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); ChnSettings[i].dwFlags = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // ChnSettings[i].nVolume - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); ChnSettings[i].nVolume = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // ChnSettings[i].szName - memcpy(&ChnSettings[i].szName[0],lpStream+streamPos,len); + memcpy(&ChnSettings[i].szName[0],lpStream+dwMemPos,len); SetNullTerminator(ChnSettings[i].szName); - streamPos += len; + dwMemPos += len; } // Song mix plugins // size of mix plugins data ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - streamPos += sizeof(DWORD); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); + dwMemPos += sizeof(DWORD); // mix plugins ASSERT_CAN_READ(id); - streamPos += LoadMixPlugins(lpStream+streamPos, id); + dwMemPos += LoadMixPlugins(lpStream+dwMemPos, id); // Song midi config // midi cfg data length ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); - streamPos += sizeof(DWORD); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); + dwMemPos += sizeof(DWORD); // midi cfg ASSERT_CAN_READ(id); if (id<=sizeof(m_MidiCfg)) { - memcpy(&m_MidiCfg,lpStream+streamPos,id); - streamPos += id; + memcpy(&m_MidiCfg,lpStream+dwMemPos,id); + dwMemPos += id; } // Song Instruments // m_nInstruments ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nInstruments = (INSTRUMENTINDEX)id; if(m_nInstruments > MAX_INSTRUMENTS) return false; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // path string length (=_MAX_PATH) ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); len = id; if(len > _MAX_PATH) return false; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // instruments' paths for(i=0; i<m_nInstruments; i++){ ASSERT_CAN_READ(len); - memcpy(&m_szInstrumentPath[i][0],lpStream+streamPos,len); + memcpy(&m_szInstrumentPath[i][0],lpStream+dwMemPos,len); SetNullTerminator(m_szInstrumentPath[i]); - streamPos += len; + dwMemPos += len; } // Song Orders // size of order array (=MAX_ORDERS) ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); size = id; if(size > MAX_ORDERS) return false; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // order data ASSERT_CAN_READ(size); - Order.ReadAsByte(lpStream+streamPos, size, dwMemLength-streamPos); - streamPos += size; + Order.ReadAsByte(lpStream+dwMemPos, size, dwMemLength-dwMemPos); + dwMemPos += size; @@ -220,38 +215,38 @@ ASSERT_CAN_READ(3*4); // number of patterns (=MAX_PATTERNS) - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); size = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); if(size > MAX_PATTERNS) return false; // m_nPatternNames - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); m_nPatternNames = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // pattern name string length (=MAX_PATTERNNAME) - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); len = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // m_lpszPatternNames if (len<=MAX_PATTERNNAME && m_nPatternNames<=MAX_PATTERNS) { m_lpszPatternNames = new char[m_nPatternNames * len]; ASSERT_CAN_READ(m_nPatternNames * len); - memcpy(&m_lpszPatternNames[0],lpStream+streamPos,m_nPatternNames * len); + memcpy(&m_lpszPatternNames[0],lpStream+dwMemPos,m_nPatternNames * len); } else return false; - streamPos += m_nPatternNames * len; + dwMemPos += m_nPatternNames * len; // modcommand data length ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); n = id; if(n != 6) return false; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); for(PATTERNINDEX npat=0; npat<size; npat++) { @@ -260,24 +255,24 @@ // Patterns[npat].GetNumRows() ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); if(id > MAX_PATTERN_ROWS) return false; Patterns[npat].Resize(id, false); - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // Try to allocate & read only sized patterns if(Patterns[npat].GetNumRows()){ // Allocate pattern if(Patterns.Insert(npat, Patterns[npat].GetNumRows())){ - streamPos += m_nChannels * Patterns[npat].GetNumRows() * n; + dwMemPos += m_nChannels * Patterns[npat].GetNumRows() * n; continue; } // Pattern data long datasize = m_nChannels * Patterns[npat].GetNumRows() * n; //if (streamPos+datasize<=dwMemLength) { - if(Patterns[npat].ReadITPdata(lpStream, streamPos, datasize, dwMemLength)) + if(Patterns[npat].ReadITPdata(lpStream, dwMemPos, datasize, dwMemLength)) { ErrorBox(IDS_ERR_FILEOPEN, NULL); return false; @@ -294,17 +289,17 @@ // Read original number of samples ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); if(id > MAX_SAMPLES) return false; m_nSamples = (SAMPLEINDEX)id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // Read number of embeded samples ASSERT_CAN_READ(4); - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); if(id > MAX_SAMPLES) return false; n = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); // Read samples for(i=0; i<n; i++){ @@ -312,22 +307,22 @@ ASSERT_CAN_READ(4 + sizeof(ITSAMPLESTRUCT) + 4); // Sample id number - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); nsmp = id; - streamPos += sizeof(DWORD); + dwMemPos += sizeof(DWORD); if(nsmp < 1 || nsmp >= MAX_SAMPLES) return false; // Sample struct - memcpy(&pis,lpStream+streamPos,sizeof(ITSAMPLESTRUCT)); - streamPos += sizeof(ITSAMPLESTRUCT); + memcpy(&pis,lpStream+dwMemPos,sizeof(ITSAMPLESTRUCT)); + dwMemPos += sizeof(ITSAMPLESTRUCT); // Sample length - memcpy(&id,lpStream+streamPos,sizeof(DWORD)); + memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); len = id; - streamPos += sizeof(DWORD); - if(streamPos >= dwMemLength || len > dwMemLength - streamPos) return false; + dwMemPos += sizeof(DWORD); + if(dwMemPos >= dwMemLength || len > dwMemLength - dwMemPos) return false; // Copy sample struct data if(pis.id == 0x53504D49) @@ -371,8 +366,8 @@ if (pis.flags & 4) flags |= RSF_STEREO; } // Read sample data - ReadSample(&Samples[nsmp], flags, (LPSTR)(lpStream+streamPos), len); - streamPos += len; + ReadSample(&Samples[nsmp], flags, (LPSTR)(lpStream+dwMemPos), len); + dwMemPos += len; memcpy(m_szNames[nsmp], pis.name, 26); } } @@ -400,9 +395,9 @@ // Extra info data __int32 fcode = 0; - LPCBYTE ptr = lpStream + min(streamPos, dwMemLength); + LPCBYTE ptr = lpStream + min(dwMemPos, dwMemLength); - if (streamPos <= dwMemLength - 4) { + if (dwMemPos <= dwMemLength - 4) { fcode = (*((__int32 *)ptr)); } @@ -459,8 +454,6 @@ } return true; - - #undef ASSERT_CAN_READ } Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mdl.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_mdl.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -10,7 +10,7 @@ // DigiTracker (MDL) module loader // ////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" //#define MDL_LOG Modified: trunk/OpenMPT/soundlib/Load_med.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_med.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -8,7 +8,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" //#define MED_LOG Modified: trunk/OpenMPT/soundlib/Load_mid.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mid.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_mid.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -11,7 +11,7 @@ // MIDI loader // ////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #include "dlsbank.h" #pragma warning(disable:4244) Modified: trunk/OpenMPT/soundlib/Load_mo3.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mo3.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_mo3.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -7,7 +7,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #ifdef MODPLUG_TRACKER #include "../mptrack/moddoc.h" #endif // MODPLUG_TRACKER Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -9,7 +9,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/soundlib/Load_mt2.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mt2.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_mt2.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -1,5 +1,5 @@ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" //#define MT2DEBUG Modified: trunk/OpenMPT/soundlib/Load_mtm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_mtm.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -9,7 +9,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" ////////////////////////////////////////////////////////// // MTM file support (import only) Modified: trunk/OpenMPT/soundlib/Load_okt.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_okt.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_okt.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -10,7 +10,7 @@ // Oktalyzer (OKT) module loader // ////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" // IFF chunk names #define OKTCHUNKID_CMOD 0x434D4F44 @@ -99,12 +99,11 @@ void Read_OKT_Pattern(const BYTE *lpStream, const DWORD dwMemLength, const PATTERNINDEX nPat, CSoundFile *pSndFile) //----------------------------------------------------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return; + #define ASSERT_CAN_READ_OKTPAT(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwMemLength, x, return); DWORD dwMemPos = 0; - ASSERT_CAN_READ(2); + ASSERT_CAN_READ_OKTPAT(2); ROWINDEX nRows = CLAMP(BigEndianW(*(uint16 *)(lpStream + dwMemPos)), 1, MAX_PATTERN_ROWS); dwMemPos += 2; @@ -119,7 +118,7 @@ m = mrow; for(CHANNELINDEX nChn = 0; nChn < nChns; nChn++, m++) { - ASSERT_CAN_READ(4); + ASSERT_CAN_READ_OKTPAT(4); m->note = lpStream[dwMemPos++]; m->instr = lpStream[dwMemPos++]; int8 fxcmd = lpStream[dwMemPos++]; @@ -263,16 +262,13 @@ } } - #undef ASSERT_CAN_READ + #undef ASSERT_CAN_READ_OKTPAT } bool CSoundFile::ReadOKT(const BYTE *lpStream, const DWORD dwMemLength) //--------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - DWORD dwMemPos = 0; ASSERT_CAN_READ(8); @@ -438,6 +434,4 @@ SetModFlag(MSF_COMPATIBLE_PLAY, true); return true; - - #undef ASSERT_CAN_READ } Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -19,7 +19,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #ifdef MODPLUG_TRACKER #include "../mptrack/moddoc.h" #endif // MODPLUG_TRACKER @@ -132,9 +132,6 @@ bool CSoundFile::ReadPSM(const LPCBYTE lpStream, const DWORD dwMemLength) //----------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - DWORD dwMemPos = 0; bool bNewFormat = false; // The game "Sinaria" uses a slightly modified PSM structure @@ -809,8 +806,6 @@ } return true; - - #undef ASSERT_CAN_READ } //////////////////////////////// @@ -875,9 +870,6 @@ bool CSoundFile::ReadPSM16(const LPCBYTE lpStream, const DWORD dwMemLength) //----------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - DWORD dwMemPos = 0; ASSERT_CAN_READ(sizeof(PSM16HEADER)); @@ -1210,7 +1202,4 @@ } return true; - - #undef ASSERT_CAN_READ - } Modified: trunk/OpenMPT/soundlib/Load_ptm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ptm.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_ptm.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -12,7 +12,7 @@ // PTM PolyTracker module loader // ////////////////////////////////////////////// #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -9,8 +9,7 @@ */ #include "stdafx.h" -#include "sndfile.h" -#include "../mptrack/misc_util.h" +#include "Loaders.h" #include "../mptrack/version.h" #ifdef MODPLUG_TRACKER #include "../mptrack/moddoc.h" Modified: trunk/OpenMPT/soundlib/Load_stm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_stm.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_stm.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -8,7 +8,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/soundlib/Load_ult.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ult.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_ult.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -7,7 +7,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" enum { @@ -33,9 +33,6 @@ STATIC_ASSERT(sizeof(ULT_SAMPLE) >= 64); #pragma pack() -#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 @@ -147,20 +144,22 @@ static int ReadULTEvent(MODCOMMAND *note, const BYTE *lpStream, DWORD *dwMP, const DWORD dwMemLength) //--------------------------------------------------------------------------------------------------- { + #define ASSERT_CAN_READ_ULTENV(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwMemLength, x, return 0); + DWORD dwMemPos = *dwMP; uint8 b, repeat = 1; uint8 cmd1, cmd2; // 1 = vol col, 2 = fx col in the original schismtracker code uint8 param1, param2; - ASSERT_CAN_READ(1) + ASSERT_CAN_READ_ULTENV(1) b = lpStream[dwMemPos++]; if (b == 0xFC) // repeat event { - ASSERT_CAN_READ(2); + ASSERT_CAN_READ_ULTENV(2); repeat = lpStream[dwMemPos++]; b = lpStream[dwMemPos++]; } - ASSERT_CAN_READ(4) + ASSERT_CAN_READ_ULTENV(4) note->note = (b > 0 && b < 61) ? b + 36 : NOTE_NONE; note->instr = lpStream[dwMemPos++]; b = lpStream[dwMemPos++]; @@ -231,6 +230,8 @@ *dwMP = dwMemPos; return repeat; + + #undef ASSERT_CAN_READ_ULTENV } // Functor for postfixing ULT patterns (this is easier than just remembering everything WHILE we're reading the pattern events) @@ -468,5 +469,3 @@ } return true; } - -#undef ASSERT_CAN_READ Modified: trunk/OpenMPT/soundlib/Load_umx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_umx.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_umx.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -7,7 +7,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #define MODMAGIC_OFFSET (20+31*30+130) Modified: trunk/OpenMPT/soundlib/Load_wav.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_wav.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_wav.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -8,7 +8,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #ifndef WAVE_FORMAT_EXTENSIBLE #define WAVE_FORMAT_EXTENSIBLE 0xFFFE Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -7,7 +7,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #include "../mptrack/version.h" #include "../mptrack/misc_util.h" Added: trunk/OpenMPT/soundlib/Loaders.h =================================================================== --- trunk/OpenMPT/soundlib/Loaders.h (rev 0) +++ trunk/OpenMPT/soundlib/Loaders.h 2010-08-05 11:44:10 UTC (rev 676) @@ -0,0 +1,17 @@ +/* + * Loaders.h + * --------- + * Purpose: Provide common functions for module loaders + * Notes : (currently none) + * Authors: OpenMPT Devs + * + */ + +#include "Sndfile.h" + +// Execute "action" if "request" bytes cannot be read from stream +#define ASSERT_CAN_READ_PROTOTYPE(position, length, request_bytes, action) \ + if( position > length || request_bytes > length - position) action; + +// "Default" macro for checking if x bytes can be read from stream. +#define ASSERT_CAN_READ(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwMemLength, x, return false); Modified: trunk/OpenMPT/soundlib/load_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2010-08-04 22:49:32 UTC (rev 675) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2010-08-05 11:44:10 UTC (rev 676) @@ -11,7 +11,7 @@ */ #include "stdafx.h" -#include "sndfile.h" +#include "Loaders.h" #ifndef ZLIB_WINAPI #define ZLIB_WINAPI #endif // ZLIB_WINAPI @@ -210,9 +210,7 @@ //-------------------------------------------------------------------------------------------------------------------------------------------- { // version false = AMFF, true = AM - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - + DWORD dwMemPos = 0; ASSERT_CAN_READ(1); @@ -346,7 +344,6 @@ return true; - #undef ASSERT_CAN_READ } @@ -443,10 +440,7 @@ bool CSoundFile::ReadAM(const LPCBYTE lpStream, const DWORD dwMemLength) //---------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - #define ASSERT_CAN_READ_CHUNK(x) \ - if( dwMemPos > dwChunkEnd || x > dwChunkEnd - dwMemPos ) break; + #define ASSERT_CAN_READ_CHUNK(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwChunkEnd, x, break); DWORD dwMemPos = 0; @@ -773,16 +767,12 @@ return true; - #undef ASSERT_CAN_READ #undef ASSERT_CAN_READ_CHUNK } bool CSoundFile::ReadJ2B(const LPCBYTE lpStream, const DWORD dwMemLength) //----------------------------------------------------------------------- { - #define ASSERT_CAN_READ(x) \ - if( dwMemPos > dwMemLength || x > dwMemLength - dwMemPos ) return false; - DWORD dwMemPos = 0; ASSERT_CAN_READ(sizeof(J2BHEADER)); @@ -816,6 +806,4 @@ delete[] bOutput; return bResult; - - #undef ASSERT_CAN_READ } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |