From: <sag...@us...> - 2011-03-26 17:57:40
|
Revision: 832 http://modplug.svn.sourceforge.net/modplug/?rev=832&view=rev Author: saga-games Date: 2011-03-26 17:57:33 +0000 (Sat, 26 Mar 2011) Log Message: ----------- [New] Most MPT hacks in modules can now be found through View -> Find MPT Hacks in Song. Modified Paths: -------------- trunk/OpenMPT/mptrack/MPTHacks.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/soundlib/mod_specifications.h Modified: trunk/OpenMPT/mptrack/MPTHacks.cpp =================================================================== --- trunk/OpenMPT/mptrack/MPTHacks.cpp 2011-03-26 15:16:39 UTC (rev 831) +++ trunk/OpenMPT/mptrack/MPTHacks.cpp 2011-03-26 17:57:33 UTC (rev 832) @@ -85,8 +85,8 @@ }; // Go through the module to find out if it contains any hacks introduced by (Open)MPT -bool CModDoc::HasMPTHacks(bool autofix) -//------------------------------------- +bool CModDoc::HasMPTHacks(const bool autofix) +//------------------------------------------- { const CModSpecifications *originalSpecs = &m_SndFile.GetModSpecifications(); // retrieve original (not hacked) specs. @@ -107,6 +107,7 @@ } bool foundHacks = false, foundHere = false; + CString message; ClearLog(); // Check for plugins @@ -126,7 +127,8 @@ // Pattern count if(m_SndFile.GetNumPatterns() > originalSpecs->patternsMax) { - AddToLog("Found too many patterns\n"); + message.Format("Found too many patterns (%d allowed)\n", originalSpecs->patternsMax); + AddToLog(message); foundHacks = true; // REQUIRES (INTELLIGENT) AUTOFIX } @@ -146,7 +148,10 @@ } } if(foundHere) - AddToLog("Found incompatible pattern lengths\n"); + { + message.Format("Found incompatible pattern lengths (must be between %d and %d rows)\n", originalSpecs->patternRowsMin, originalSpecs->patternRowsMax); + AddToLog(message); + } // Check for invalid pattern commands foundHere = false; @@ -179,7 +184,8 @@ // Check for too many channels if(m_SndFile.GetNumChannels() > originalSpecs->channelsMax || m_SndFile.GetNumChannels() < originalSpecs->channelsMin) { - AddToLog("Found incompatible channel count\n"); + message.Format("Found incompatible channel count (must be between %d and %d channels)\n", originalSpecs->channelsMin, originalSpecs->channelsMax); + AddToLog(message); foundHacks = true; // REQUIRES (INTELLIGENT) AUTOFIX } @@ -203,7 +209,8 @@ // Check for too many samples if(m_SndFile.GetNumSamples() > originalSpecs->samplesMax) { - AddToLog("Found too many samples\n"); + message.Format("Found too many samples (%d allowed)\n", originalSpecs->samplesMax); + AddToLog(message); foundHacks = true; // REQUIRES (INTELLIGENT) AUTOFIX } @@ -211,7 +218,8 @@ // Check for too many instruments if(m_SndFile.GetNumInstruments() > originalSpecs->instrumentsMax) { - AddToLog("Found too many instruments\n"); + message.Format("Found too many instruments (%d allowed)\n", originalSpecs->instrumentsMax); + AddToLog(message); foundHacks = true; // REQUIRES (INTELLIGENT) AUTOFIX } @@ -253,7 +261,8 @@ // Check for too many orders if(m_SndFile.Order.GetLengthTailTrimmed() > originalSpecs->ordersMax) { - AddToLog("Found too many orders\n"); + message.Format("Found too many orders (%d allowed)\n", originalSpecs->ordersMax); + AddToLog(message); foundHacks = true; // REQUIRES (INTELLIGENT) AUTOFIX } @@ -261,7 +270,8 @@ // Check for invalid default tempo if(m_SndFile.m_nDefaultTempo > originalSpecs->tempoMax || m_SndFile.m_nDefaultTempo < originalSpecs->tempoMin) { - AddToLog("Found incompatible default tempo\n"); + message.Format("Found incompatible default tempo (must be between %d and %d)\n", originalSpecs->tempoMin, originalSpecs->tempoMax); + AddToLog(message); foundHacks = true; if(autofix) m_SndFile.m_nDefaultTempo = CLAMP(m_SndFile.m_nDefaultTempo, originalSpecs->tempoMin, originalSpecs->tempoMax); @@ -270,7 +280,8 @@ // Check for invalid default speed if(m_SndFile.m_nDefaultSpeed > originalSpecs->speedMax || m_SndFile.m_nDefaultSpeed < originalSpecs->speedMin) { - AddToLog("Found incompatible default speed\n"); + message.Format("Found incompatible default speed (must be between %d and %d)\n", originalSpecs->speedMin, originalSpecs->speedMax); + AddToLog(message); foundHacks = true; if(autofix) m_SndFile.m_nDefaultSpeed = CLAMP(m_SndFile.m_nDefaultSpeed, originalSpecs->speedMin, originalSpecs->speedMax); @@ -312,7 +323,7 @@ // Check for new tempo modes if(m_SndFile.m_nTempoMode != tempo_mode_classic) { - AddToLog("Found incompatible tempo mode\n"); + AddToLog("Found incompatible tempo mode (only classic tempo mode allowed)\n"); foundHacks = true; if(autofix) m_SndFile.m_nTempoMode = tempo_mode_classic; @@ -358,7 +369,7 @@ if(m_SndFile.m_nMixLevels != mixLevels_compatible) { - AddToLog("Found incorrect mix levels\n"); + AddToLog("Found incorrect mix levels (only compatible mix levels allowed)\n"); foundHacks = true; if(autofix) m_SndFile.m_nMixLevels = mixLevels_compatible; @@ -366,6 +377,6 @@ if(autofix && foundHacks) SetModified(); - + return foundHacks; } Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-03-26 15:16:39 UTC (rev 831) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-03-26 17:57:33 UTC (rev 832) @@ -53,6 +53,7 @@ ON_COMMAND(ID_VIEW_COMMENTS, OnEditComments) ON_COMMAND(ID_VIEW_GRAPH, OnEditGraph) //rewbs.graph ON_COMMAND(ID_VIEW_EDITHISTORY, OnViewEditHistory) + ON_COMMAND(ID_VIEW_MPTHACKS, OnViewMPTHacks) ON_COMMAND(ID_INSERT_PATTERN, OnInsertPattern) ON_COMMAND(ID_INSERT_SAMPLE, OnInsertSample) ON_COMMAND(ID_INSERT_INSTRUMENT, OnInsertInstrument) @@ -3513,6 +3514,18 @@ } +void CModDoc::OnViewMPTHacks() +//---------------------------- +{ + if(!HasMPTHacks()) + { + AddToLog("No hacks found.\n"); + } + ShowLog(); + ClearLog(); +} + + LRESULT CModDoc::OnCustomKeyMsg(WPARAM wParam, LPARAM /*lParam*/) //--------------------------------------------------------------- { Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2011-03-26 15:16:39 UTC (rev 831) +++ trunk/OpenMPT/mptrack/Moddoc.h 2011-03-26 17:57:33 UTC (rev 832) @@ -346,7 +346,7 @@ bool RestartPosToPattern(); - bool HasMPTHacks(bool autofix = false); + bool HasMPTHacks(const bool autofix = false); void FixNullStrings(); @@ -436,6 +436,7 @@ afx_msg void OnPatternPlay(); //rewbs.customKeys afx_msg void OnPatternPlayNoLoop(); //rewbs.customKeys afx_msg void OnViewEditHistory(); + afx_msg void OnViewMPTHacks(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2011-03-26 15:16:39 UTC (rev 831) +++ trunk/OpenMPT/mptrack/mptrack.rc 2011-03-26 17:57:33 UTC (rev 832) @@ -2008,12 +2008,13 @@ MENUITEM "&Tree", IDD_TREEVIEW END MENUITEM SEPARATOR - MENUITEM "Set&up...", ID_VIEW_OPTIONS - MENUITEM "Add &Plugin...", ID_PLUGIN_SETUP - MENUITEM "Channel &Manager...", ID_CHANNEL_MANAGER - MENUITEM "Song Properties...", ID_VIEW_SONGPROPERTIES + MENUITEM "S&etup...", ID_VIEW_OPTIONS + MENUITEM "Pl&ugin Manager...", ID_PLUGIN_SETUP + MENUITEM "Ch&annel Manager...", ID_CHANNEL_MANAGER + MENUITEM "Song P&roperties...", ID_VIEW_SONGPROPERTIES MENUITEM "&MIDI Mapping...", ID_VIEW_MIDIMAPPING MENUITEM "Edit &History...", ID_VIEW_EDITHISTORY + MENUITEM "Find MPT Hacks in Song", ID_VIEW_MPTHACKS END POPUP "&Window" BEGIN Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2011-03-26 15:16:39 UTC (rev 831) +++ trunk/OpenMPT/mptrack/resource.h 2011-03-26 17:57:33 UTC (rev 832) @@ -1184,6 +1184,7 @@ #define ID_SAMPLE_GRID 60453 #define ID_SAMPLE_QUICKFADE 60454 #define ID_EDIT_MIXPASTE_ITSTYLE 60455 +#define ID_VIEW_MPTHACKS 60456 // Next default values for new objects // @@ -1191,7 +1192,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 529 -#define _APS_NEXT_COMMAND_VALUE 60456 +#define _APS_NEXT_COMMAND_VALUE 60457 #define _APS_NEXT_CONTROL_VALUE 2435 #define _APS_NEXT_SYMED_VALUE 901 #endif Modified: trunk/OpenMPT/soundlib/mod_specifications.h =================================================================== --- trunk/OpenMPT/soundlib/mod_specifications.h 2011-03-26 15:16:39 UTC (rev 831) +++ trunk/OpenMPT/soundlib/mod_specifications.h 2011-03-26 17:57:33 UTC (rev 832) @@ -193,7 +193,7 @@ false, // No notecut. true, // Has noteoff. false, // No notefade. - 255, // Pattern max. + 256, // Pattern max. 255, // Order max. 1, // Channel min 32, // Channel max @@ -233,8 +233,8 @@ false, // No notecut. true, // Has noteoff. false, // No notefade. - 255, // Pattern max. - 256, // Order max. + 256, // Pattern max. + 255, // Order max. 1, // Channel min 127, // Channel max 32, // Min tempo @@ -272,7 +272,7 @@ true, // Has notecut. false, // No noteoff. false, // No notefade. - 99, // Pattern max. + 100, // Pattern max. 255, // Order max. 1, // Channel min 32, // Channel max @@ -312,7 +312,7 @@ true, // Has notecut. false, // No noteoff. false, // No notefade. - 99, // Pattern max. + 100, // Pattern max. 255, // Order max. 1, // Channel min 32, // Channel max This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-01 14:59:14
|
Revision: 834 http://modplug.svn.sourceforge.net/modplug/?rev=834&view=rev Author: saga-games Date: 2011-04-01 14:59:06 +0000 (Fri, 01 Apr 2011) Log Message: ----------- [Mod] Package Template: added latin-american keymaps (tx jmkz), as well as coda's US MPT/IT keymap. [Mod] Added latin-american keymap autodetection to installer. Modified Paths: -------------- trunk/OpenMPT/installer/install.iss Added Paths: ----------- trunk/OpenMPT/packageTemplate/extraKeymaps/US_mptit_(coda).mkb trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_it-mpt_jmkz.mkb trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_mpt_jmkz.mkb Modified: trunk/OpenMPT/installer/install.iss =================================================================== --- trunk/OpenMPT/installer/install.iss 2011-03-27 12:41:58 UTC (rev 833) +++ trunk/OpenMPT/installer/install.iss 2011-04-01 14:59:06 UTC (rev 834) @@ -208,6 +208,14 @@ begin keyboardFilepath := 'DE_jojo'; end; + $0a: // Spanish + begin + // Spanish latin-american keymap, so we ignore Spain. + if(GetUILanguage <> $0c0a) then + begin + keyboardFilepath := 'es-LA_mpt_(jmkz)'; + end; + end; $0c: // French begin keyboardFilepath := 'FR_mpt_(legovitch)'; Added: trunk/OpenMPT/packageTemplate/extraKeymaps/US_mptit_(coda).mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/US_mptit_(coda).mkb (rev 0) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/US_mptit_(coda).mkb 2011-04-01 14:59:06 UTC (rev 834) @@ -0,0 +1,338 @@ +//-------- OpenMPT key binding definition file ------- +//-Format is: - +//- Context:Command ID:Modifiers:Key:KeypressEventType //Comments - +//---------------------------------------------------------------------- +version:1 + +//----( Global Context (0) )------------ +0:1347:2:78:1 //File/New: Ctrl+N (KeyDown) +0:1346:0:120:1 //File/Open: F9 (KeyDown) +0:1346:2:82:1 //File/Open: Ctrl+R (KeyDown) +0:1348:2:82:2 //File/Close: Ctrl+R (KeyUp) +0:1349:2:83:1 //File/Save: Ctrl+S (KeyDown) +0:1350:2:87:1 //File/Save As: Ctrl+W (KeyDown) +0:1350:0:121:1 //File/Save As: F10 (KeyDown) +0:1030:0:116:2 //Play song/Pause song: F5 (KeyUp) +0:1031:0:119:1 //Pause song: F8 (KeyDown) +0:1029:2:116:1 //Play song from start: Ctrl+F5 (KeyDown) +0:1028:0:118:1 //Play song from cursor: F7 (KeyDown) +0:1027:0:117:5 //Play pattern from start: F6 (KeyDown|KeyHold) +0:1026:2:118:5 //Play pattern from cursor: Ctrl+F7 (KeyDown|KeyHold) +0:1374:2:80:1 //Estimate Song Length: Ctrl+P (KeyDown) +0:1359:2:8:1 //Undo: Ctrl+Backspace (KeyDown) +0:1360:2:88:1 //Cut: Ctrl+X (KeyDown) +0:1361:2:67:1 //Copy: Ctrl+C (KeyDown) +0:1362:2:86:1 //Paste: Ctrl+V (KeyDown) +0:1686:4:77:1 //Mix Paste (old IT Style): Alt+M (KeyDown) +0:1793:3:86:1 //Paste Flood: Shift+Ctrl+V (KeyDown) +0:1021:0:122:1 //View General: F11 (KeyDown) +0:1022:0:113:1 //View Pattern: F2 (KeyDown) +0:1022:0:116:1 //View Pattern: F5 (KeyDown) +0:1023:0:114:1 //View Samples: F3 (KeyDown) +0:1024:0:115:1 //View Instruments: F4 (KeyDown) +0:1025:1:120:1 //View Comments: Shift+F9 (KeyDown) +0:1367:4:122:1 //Toggle Main View: Alt+F11 (KeyDown) +0:1368:4:122:2 //Toggle Tree View: Alt+F11 (KeyUp) +0:1369:0:123:1 //View Options: F12 (KeyDown) +0:1370:0:112:1 //Help (to do): F1 (KeyDown) +0:1032:1:188:5 //Previous instrument: Shift+, (KeyDown|KeyHold) +0:1032:2:38:5 //Previous instrument: Ctrl+Up (KeyDown|KeyHold) +0:1033:1:190:5 //Next instrument: Shift+. (KeyDown|KeyHold) +0:1033:2:40:5 //Next instrument: Ctrl+Down (KeyDown|KeyHold) +0:1036:0:111:5 //Previous octave: Num / (KeyDown|KeyHold) +0:1037:0:106:5 //Next octave: Num * (KeyDown|KeyHold) +0:1034:2:37:5 //Previous order: Ctrl+Left (KeyDown|KeyHold) +0:1035:2:39:5 //Next order: Ctrl+Right (KeyDown|KeyHold) + +//----( General Context [bottom] (1) )------------ + +//----( Pattern Context [bottom] (2) )------------ +2:1017:2:34:5 //Jump down by measure: Ctrl+Page Down (KeyDown|KeyHold) +2:1018:2:33:5 //Jump up by measure: Ctrl+Page Up (KeyDown|KeyHold) +2:1338:4:34:5 //Jump down by beat: Alt+Page Down (KeyDown|KeyHold) +2:1339:4:33:5 //Jump up by beat: Alt+Page Up (KeyDown|KeyHold) +2:1019:0:34:5 //Snap down to measure: Page Down (KeyDown|KeyHold) +2:1020:0:33:5 //Snap up to measure: Page Up (KeyDown|KeyHold) +2:1340:6:34:5 //Snap down to beat: Ctrl+Alt+Page Down (KeyDown|KeyHold) +2:1341:6:33:5 //Snap up to beat: Ctrl+Alt+Page Up (KeyDown|KeyHold) +2:1038:0:40:5 //Navigate down by 1 row: Down (KeyDown|KeyHold) +2:1039:0:38:5 //Navigate up by 1 row: Up (KeyDown|KeyHold) +2:1040:0:37:5 //Navigate left: Left (KeyDown|KeyHold) +2:1041:0:39:5 //Navigate right: Right (KeyDown|KeyHold) +2:1042:0:9:5 //Navigate to next channel: Tab (KeyDown|KeyHold) +2:1043:1:9:5 //Navigate to previous channel: Shift+Tab (KeyDown|KeyHold) +2:1044:0:36:1 //Go to first channel: Home (KeyDown) +2:1045:2:36:1 //Go to first row: Ctrl+Home (KeyDown) +2:1046:6:36:1 //Go to first row of first channel: Ctrl+Alt+Home (KeyDown) +2:1047:0:35:1 //Go to last channel: End (KeyDown) +2:1048:2:35:1 //Go to last row: Ctrl+End (KeyDown) +2:1049:6:35:1 //Go to last row of last channel: Ctrl+Alt+End (KeyDown) +2:1050:1:16:1 //Selection key: Shift+Shift (KeyDown) +2:1051:2:17:1 //Copy select key: Ctrl+Ctrl (KeyDown) +2:1011:4:76:1 //Select channel / Select all: Alt+L (KeyDown) +2:1003:0:13:1 //Quick copy: Enter (KeyDown) +2:1004:0:32:5 //Quick paste: Space (KeyDown|KeyHold) +2:1002:0:56:1 //Play row: 8 (KeyDown) +2:1317:4:18:1 //Set row jump on note entry: Alt+Alt (KeyDown) +2:1062:0:93:1 //Show note properties: Application (KeyDown) +2:1063:2:93:1 //Show context (right-click) menu: Ctrl+Application (KeyDown) +2:1005:4:120:1 //Mute current channel: Alt+F9 (KeyDown) +2:1006:4:121:1 //Solo current channel: Alt+F10 (KeyDown) +2:1671:4:67:1 //Copy and lose selection: Alt+C (KeyDown) +2:1007:4:81:5 //Transpose +1: Alt+Q (KeyDown|KeyHold) +2:1008:4:65:5 //Transpose -1: Alt+A (KeyDown|KeyHold) +2:1009:6:81:5 //Transpose +12: Ctrl+Alt+Q (KeyDown|KeyHold) +2:1010:6:65:5 //Transpose -12: Ctrl+Alt+A (KeyDown|KeyHold) +2:1012:4:74:1 //Amplify selection: Alt+J (KeyDown) +2:1014:4:75:1 //Interpolate volume: Alt+K (KeyDown) +2:1015:4:88:1 //Interpolate effect: Alt+X (KeyDown) +2:1016:4:66:1 //Open effect visualizer: Alt+B (KeyDown) +2:1013:4:83:1 //Apply current instrument: Alt+S (KeyDown) +2:1664:0:46:1 //Clear field (IT Style): Delete (KeyDown) +2:1665:0:190:5 //Clear field and step (IT Style): . (KeyDown|KeyHold) +2:1061:0:8:1 //Delete rows: Backspace (KeyDown) +2:1377:1:46:1 //Delete all rows: Shift+Delete (KeyDown) +2:1378:0:45:5 //Insert Row: Insert (KeyDown|KeyHold) +2:1379:1:45:5 //Insert All Rows: Shift+Insert (KeyDown|KeyHold) +2:1055:0:109:1 //Previous pattern: Num - (KeyDown) +2:1054:0:107:1 //Next pattern: Num + (KeyDown) + +//----( Pattern Context [bottom] - Note Col (3) )------------ +3:1064:0:90:1 //Base octave C: Z (KeyDown) +3:1065:0:83:1 //Base octave C#: S (KeyDown) +3:1066:0:88:1 //Base octave D: X (KeyDown) +3:1067:0:68:1 //Base octave D#: D (KeyDown) +3:1068:0:67:1 //Base octave E: C (KeyDown) +3:1069:0:86:1 //Base octave F: V (KeyDown) +3:1070:0:71:1 //Base octave F#: G (KeyDown) +3:1071:0:66:1 //Base octave G: B (KeyDown) +3:1072:0:72:1 //Base octave G#: H (KeyDown) +3:1073:0:78:1 //Base octave A: N (KeyDown) +3:1074:0:74:1 //Base octave A#: J (KeyDown) +3:1075:0:77:1 //Base octave B: M (KeyDown) +3:1076:0:81:1 //Base octave +1 C: Q (KeyDown) +3:1076:0:188:1 //Base octave +1 C: , (KeyDown) +3:1077:0:50:1 //Base octave +1 C#: 2 (KeyDown) +3:1077:0:76:1 //Base octave +1 C#: L (KeyDown) +3:1078:0:87:1 //Base octave +1 D: W (KeyDown) +3:1079:0:51:1 //Base octave +1 D#: 3 (KeyDown) +3:1080:0:69:1 //Base octave +1 E: E (KeyDown) +3:1081:0:82:1 //Base octave +1 F: R (KeyDown) +3:1082:0:53:1 //Base octave +1 F#: 5 (KeyDown) +3:1083:0:84:1 //Base octave +1 G: T (KeyDown) +3:1084:0:54:1 //Base octave +1 G#: 6 (KeyDown) +3:1085:0:89:1 //Base octave +1 A: Y (KeyDown) +3:1086:0:55:1 //Base octave +1 A#: 7 (KeyDown) +3:1087:0:85:1 //Base octave +1 B: U (KeyDown) +3:1088:0:73:1 //Base octave +2 C: I (KeyDown) +3:1089:0:57:1 //Base octave +2 C#: 9 (KeyDown) +3:1090:0:79:1 //Base octave +2 D: O (KeyDown) +3:1091:0:48:1 //Base octave +2 D#: 0 (KeyDown) +3:1092:0:80:1 //Base octave +2 E: P (KeyDown) +3:1093:0:189:1 //Base octave +2 F: - (KeyDown) +3:1212:0:96:1 //Set octave 0: Num 0 (KeyDown) +3:1213:0:97:1 //Set octave 1: Num 1 (KeyDown) +3:1214:0:98:1 //Set octave 2: Num 2 (KeyDown) +3:1215:0:99:1 //Set octave 3: Num 3 (KeyDown) +3:1216:0:52:1 //Set octave 4: 4 (KeyDown) +3:1216:0:100:1 //Set octave 4: Num 4 (KeyDown) +3:1217:0:101:1 //Set octave 5: Num 5 (KeyDown) +3:1218:0:102:1 //Set octave 6: Num 6 (KeyDown) +3:1219:0:103:1 //Set octave 7: Num 7 (KeyDown) +3:1220:0:56:1 //Set octave 8: 8 (KeyDown) +3:1220:0:104:1 //Set octave 8: Num 8 (KeyDown) +3:1221:0:105:1 //Set octave 9: Num 9 (KeyDown) +3:1316:1:16:1 //Chord Modifier: Shift+Shift (KeyDown) +3:1667:0:49:1 //Note Cut (don't remember instrument): 1 (KeyDown) +3:1668:0:192:1 //Note Off (don't remember instrument): ` (KeyDown) +3:1788:1:49:1 //Parameter control(MPTm only): Shift+1 (KeyDown) +3:1789:3:49:1 //Parameter control(smooth)(MPTm only): Shift+Ctrl+1 (KeyDown) + +//----( Pattern Context [bottom] - Ins Col (4) )------------ +4:1202:0:96:1 //Set instrument digit 0: Num 0 (KeyDown) +4:1202:0:48:1 //Set instrument digit 0: 0 (KeyDown) +4:1203:0:97:1 //Set instrument digit 1: Num 1 (KeyDown) +4:1203:0:49:1 //Set instrument digit 1: 1 (KeyDown) +4:1204:0:98:1 //Set instrument digit 2: Num 2 (KeyDown) +4:1204:0:50:1 //Set instrument digit 2: 2 (KeyDown) +4:1205:0:99:1 //Set instrument digit 3: Num 3 (KeyDown) +4:1205:0:51:1 //Set instrument digit 3: 3 (KeyDown) +4:1206:0:100:1 //Set instrument digit 4: Num 4 (KeyDown) +4:1206:0:52:1 //Set instrument digit 4: 4 (KeyDown) +4:1207:0:101:1 //Set instrument digit 5: Num 5 (KeyDown) +4:1207:0:53:1 //Set instrument digit 5: 5 (KeyDown) +4:1208:0:102:1 //Set instrument digit 6: Num 6 (KeyDown) +4:1208:0:54:1 //Set instrument digit 6: 6 (KeyDown) +4:1209:0:103:1 //Set instrument digit 7: Num 7 (KeyDown) +4:1209:0:55:1 //Set instrument digit 7: 7 (KeyDown) +4:1210:0:56:1 //Set instrument digit 8: 8 (KeyDown) +4:1211:0:105:1 //Set instrument digit 9: Num 9 (KeyDown) +4:1211:0:57:1 //Set instrument digit 9: 9 (KeyDown) + +//----( Pattern Context [bottom] - Vol Col (5) )------------ +5:1222:0:48:1 //Set volume digit 0: 0 (KeyDown) +5:1222:0:96:1 //Set volume digit 0: Num 0 (KeyDown) +5:1223:0:49:1 //Set volume digit 1: 1 (KeyDown) +5:1223:0:97:1 //Set volume digit 1: Num 1 (KeyDown) +5:1224:0:50:1 //Set volume digit 2: 2 (KeyDown) +5:1224:0:98:1 //Set volume digit 2: Num 2 (KeyDown) +5:1225:0:51:1 //Set volume digit 3: 3 (KeyDown) +5:1225:0:99:1 //Set volume digit 3: Num 3 (KeyDown) +5:1226:0:52:1 //Set volume digit 4: 4 (KeyDown) +5:1226:0:100:1 //Set volume digit 4: Num 4 (KeyDown) +5:1227:0:53:1 //Set volume digit 5: 5 (KeyDown) +5:1227:0:101:1 //Set volume digit 5: Num 5 (KeyDown) +5:1228:0:54:1 //Set volume digit 6: 6 (KeyDown) +5:1228:0:102:1 //Set volume digit 6: Num 6 (KeyDown) +5:1229:0:55:1 //Set volume digit 7: 7 (KeyDown) +5:1229:0:103:1 //Set volume digit 7: Num 7 (KeyDown) +5:1230:0:56:1 //Set volume digit 8: 8 (KeyDown) +5:1231:0:57:1 //Set volume digit 9: 9 (KeyDown) +5:1231:0:105:1 //Set volume digit 9: Num 9 (KeyDown) +5:1232:0:86:1 //Vol command - volume: V (KeyDown) +5:1233:0:80:1 //Vol command - pan: P (KeyDown) +5:1234:0:67:1 //Vol command - vol slide up: C (KeyDown) +5:1235:0:68:1 //Vol command - vol slide down: D (KeyDown) +5:1236:0:65:1 //Vol command - vol fine slide up: A (KeyDown) +5:1237:0:66:1 //Vol command - vol fine slide down: B (KeyDown) +5:1238:0:85:1 //Vol command - vibrato speed: U (KeyDown) +5:1239:0:72:1 //Vol command - vibrato: H (KeyDown) +5:1240:0:76:1 //Vol command - XM pan left: L (KeyDown) +5:1241:0:82:1 //Vol command - XM pan right: R (KeyDown) +5:1242:0:71:1 //Vol command - Portamento: G (KeyDown) +5:1243:0:70:1 //Vol command - Portamento Up: F (KeyDown) +5:1244:0:69:1 //Vol command - Portamento Down: E (KeyDown) +5:1246:0:79:1 //Vol command - Offset: O (KeyDown) + +//----( Pattern Context [bottom] - FX Col (6) )------------ + +//----( Pattern Context [bottom] - Param Col (7) )------------ +7:1247:0:48:1 //FX Param digit 0: 0 (KeyDown) +7:1248:0:49:1 //FX Param digit 1: 1 (KeyDown) +7:1249:0:50:1 //FX Param digit 2: 2 (KeyDown) +7:1250:0:51:1 //FX Param digit 3: 3 (KeyDown) +7:1251:0:52:1 //FX Param digit 4: 4 (KeyDown) +7:1252:0:53:1 //FX Param digit 5: 5 (KeyDown) +7:1253:0:54:1 //FX Param digit 6: 6 (KeyDown) +7:1254:0:55:1 //FX Param digit 7: 7 (KeyDown) +7:1255:0:56:1 //FX Param digit 8: 8 (KeyDown) +7:1256:0:57:1 //FX Param digit 9: 9 (KeyDown) +7:1257:0:65:1 //FX Param digit A: A (KeyDown) +7:1258:0:66:1 //FX Param digit B: B (KeyDown) +7:1259:0:67:1 //FX Param digit C: C (KeyDown) +7:1260:0:68:1 //FX Param digit D: D (KeyDown) +7:1261:0:69:1 //FX Param digit E: E (KeyDown) +7:1262:0:70:1 //FX Param digit F: F (KeyDown) + +//----( Sample Context [bottom] (8) )------------ +8:1673:0:13:1 //Load a Sample: Enter (KeyDown) +8:1673:4:79:1 //Load a Sample: Alt+O (KeyDown) +8:1674:4:83:1 //Save Sample: Alt+S (KeyDown) +8:1675:0:45:1 //New Sample: Insert (KeyDown) +8:1380:4:66:1 //Trim sample around loop points: Alt+B (KeyDown) +8:1380:4:76:1 //Trim sample around loop points: Alt+L (KeyDown) +8:1383:0:190:1 //Silence sample selection: . (KeyDown) +8:1384:4:78:1 //Normalise Sample: Alt+N (KeyDown) +8:1385:4:77:1 //Amplify Sample: Alt+M (KeyDown) +8:1381:4:71:1 //Reverse sample: Alt+G (KeyDown) +8:1382:0:46:1 //Delete sample selection: Delete (KeyDown) +8:1386:0:107:1 //Zoom Out: Num + (KeyDown) +8:1387:0:109:1 //Zoom In: Num - (KeyDown) +8:1784:2:73:1 //Invert sample phase: Ctrl+I (KeyDown) +8:1785:2:85:1 //Signed/Unsigned conversion: Ctrl+U (KeyDown) +8:1790:2:69:1 //Remove DC Offset: Ctrl+E (KeyDown) +8:1856:2:68:1 //Quick fade: Ctrl+D (KeyDown) +8:1857:2:76:1 //Crossfade sample loop: Ctrl+L (KeyDown) + +//----( Instrument Context [bottom] (9) )------------ +9:1837:0:107:5 //Zoom In: Num + (KeyDown|KeyHold) +9:1838:0:109:5 //Zoom Out: Num - (KeyDown|KeyHold) +9:1825:1:9:5 //Select previous envelope point: Shift+Tab (KeyDown|KeyHold) +9:1826:0:9:5 //Select next envelope point: Tab (KeyDown|KeyHold) +9:1821:0:37:5 //Move envelope point left: Left (KeyDown|KeyHold) +9:1822:0:39:5 //Move envelope point right: Right (KeyDown|KeyHold) +9:1823:0:38:5 //Move envelope point up: Up (KeyDown|KeyHold) +9:1834:0:33:5 //Move envelope point up (big step): Page Up (KeyDown|KeyHold) +9:1824:0:40:5 //Move envelope point down: Down (KeyDown|KeyHold) +9:1835:0:34:5 //Move envelope point down (big step): Page Down (KeyDown|KeyHold) +9:1827:0:45:5 //Insert envelope point: Insert (KeyDown|KeyHold) +9:1828:0:46:5 //Remove envelope point: Delete (KeyDown|KeyHold) +9:1829:0:36:1 //Set loop start: Home (KeyDown) +9:1830:0:35:1 //Set loop end: End (KeyDown) +9:1831:2:36:1 //Set sustain loop start: Ctrl+Home (KeyDown) +9:1832:2:35:1 //Set sustain loop end: Ctrl+End (KeyDown) +9:1833:2:82:1 //Toggle release node: Ctrl+R (KeyDown) + +//----( Comments Context [bottom] (10) )------------ + +//----( Unknown Context (11) )------------ + +//----( Unknown Context (12) )------------ + +//----( Plugin GUI Context (13) )------------ +13:1763:0:37:1 //Previous plugin preset: Left (KeyDown) +13:1764:0:39:1 //Next plugin preset: Right (KeyDown) +13:1782:0:38:1 //Plugin preset backward jump: Up (KeyDown) +13:1783:0:40:1 //Plugin preset forward jump: Down (KeyDown) +13:1765:2:80:1 //Randomize plugin parameters: Ctrl+P (KeyDown) +13:1839:2:82:1 //Toggle parameter recording: Ctrl+R (KeyDown) +13:1840:2:75:1 //Pass key presses to plugin: Ctrl+K (KeyDown) +13:1841:2:66:1 //Bypass plugin: Ctrl+B (KeyDown) + +//----( General Context [top] (14) )------------ + +//----( Pattern Context [top] (15) )------------ + +//----( 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:4:81:1 //Transpose +1 (note map): Alt+Q (KeyDown) +17:1842:4:65:1 //Transpose -1 (note map): Alt+A (KeyDown) +17:1845:6:81:1 //Transpose +12 (note map): Ctrl+Alt+Q (KeyDown) +17:1844:6:65:1 //Transpose -12 (note map): Ctrl+Alt+A (KeyDown) + +//----( Comments Context [top] (18) )------------ + +//----( Orderlist (19) )------------ +19:1802:0:46:5 //Delete Order: Delete (KeyDown|KeyHold) +19:1803:0:45:5 //Insert Order: Insert (KeyDown|KeyHold) +19:1804:0:13:5 //Edit Pattern: Enter (KeyDown|KeyHold) +19:1805:0:9:5 //Switch to pattern editor: Tab (KeyDown|KeyHold) +19:1794:0:37:5 //Previous Order: Left (KeyDown|KeyHold) +19:1794:0:38:5 //Previous Order: Up (KeyDown|KeyHold) +19:1795:0:39:5 //Next Order: Right (KeyDown|KeyHold) +19:1795:0:40:5 //Next Order: Down (KeyDown|KeyHold) +19:1796:0:36:5 //First Order: Home (KeyDown|KeyHold) +19:1797:0:35:5 //Last Order: End (KeyDown|KeyHold) +19:1807:0:48:5 //Pattern index digit 0: 0 (KeyDown|KeyHold) +19:1807:0:96:5 //Pattern index digit 0: Num 0 (KeyDown|KeyHold) +19:1808:0:49:5 //Pattern index digit 1: 1 (KeyDown|KeyHold) +19:1808:0:97:5 //Pattern index digit 1: Num 1 (KeyDown|KeyHold) +19:1809:0:50:5 //Pattern index digit 2: 2 (KeyDown|KeyHold) +19:1809:0:98:5 //Pattern index digit 2: Num 2 (KeyDown|KeyHold) +19:1810:0:51:5 //Pattern index digit 3: 3 (KeyDown|KeyHold) +19:1810:0:99:5 //Pattern index digit 3: Num 3 (KeyDown|KeyHold) +19:1811:0:52:5 //Pattern index digit 4: 4 (KeyDown|KeyHold) +19:1811:0:100:5 //Pattern index digit 4: Num 4 (KeyDown|KeyHold) +19:1812:0:53:5 //Pattern index digit 5: 5 (KeyDown|KeyHold) +19:1812:0:101:5 //Pattern index digit 5: Num 5 (KeyDown|KeyHold) +19:1813:0:54:5 //Pattern index digit 6: 6 (KeyDown|KeyHold) +19:1813:0:102:5 //Pattern index digit 6: Num 6 (KeyDown|KeyHold) +19:1814:0:55:5 //Pattern index digit 7: 7 (KeyDown|KeyHold) +19:1814:0:103:5 //Pattern index digit 7: Num 7 (KeyDown|KeyHold) +19:1815:0:56:5 //Pattern index digit 8: 8 (KeyDown|KeyHold) +19:1815:0:104:5 //Pattern index digit 8: Num 8 (KeyDown|KeyHold) +19:1816:0:57:5 //Pattern index digit 9: 9 (KeyDown|KeyHold) +19:1816:0:105:5 //Pattern index digit 9: Num 9 (KeyDown|KeyHold) +19:1817:0:107:5 //Increase pattern index : Num + (KeyDown|KeyHold) +19:1817:0:187:5 //Increase pattern index : = (KeyDown|KeyHold) +19:1818:0:109:5 //Decrease pattern index: Num - (KeyDown|KeyHold) +19:1818:0:189:5 //Decrease pattern index: - (KeyDown|KeyHold) +19:1853:0:73:1 //Ignore (+++) Index: I (KeyDown) +19:1854:0:32:1 //Invalid (---) Index: Space (KeyDown) Added: trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_it-mpt_jmkz.mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_it-mpt_jmkz.mkb (rev 0) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_it-mpt_jmkz.mkb 2011-04-01 14:59:06 UTC (rev 834) @@ -0,0 +1,367 @@ +//-------- OpenMPT key binding definition file ------- +//-Format is: - +//- Context:Command ID:Modifiers:Key:KeypressEventType //Comments - +//---------------------------------------------------------------------- +version:1 + +//----( Global Context (0) )------------ +0:1347:2:78:1 //File/New: Ctrl+N (KeyDown) +0:1346:2:79:1 //File/Open: Ctrl+O (KeyDown) +0:1349:2:83:1 //File/Save: Ctrl+S (KeyDown) +0:1350:3:83:1 //File/Save As: Shift+Ctrl+S (KeyDown) +0:1030:0:116:1 //Play song/Pause song: F5 (KeyDown) +0:1031:0:119:1 //Pause song: F8 (KeyDown) +0:1375:0:27:1 //Stop Song: ESC (KeyDown) +0:1029:0:117:1 //Play song from start: F6 (KeyDown) +0:1027:0:118:1 //Play pattern from start: F7 (KeyDown) +0:1026:2:118:1 //Play pattern from cursor: Ctrl+F7 (KeyDown) +0:1376:0:120:1 //Toggle Midi Record: F9 (KeyDown) +0:1359:2:90:1 //Undo: Ctrl+Z (KeyDown) +0:1360:2:88:1 //Cut: Ctrl+X (KeyDown) +0:1361:2:67:1 //Copy: Ctrl+C (KeyDown) +0:1362:2:86:1 //Paste: Ctrl+V (KeyDown) +0:1362:1:45:1 //Paste: Shift+INSERT (KeyDown) +0:1363:3:86:1 //Mix Paste: Shift+Ctrl+V (KeyDown) +0:1793:1:86:5 //Paste Flood: Shift+V (KeyDown|KeyHold) +0:1820:6:86:1 //Push Forward Paste: Ctrl+Alt+V (KeyDown) +0:1364:2:53:1 //SelectAll: Ctrl+5 (KeyDown) +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:1022:4:80:1 //View Pattern: Alt+P (KeyDown) +0:1023:4:83:1 //View Samples: Alt+S (KeyDown) +0:1024:4:78:1 //View Instruments: Alt+N (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:1032:2:111:5 //Previous instrument: Ctrl+TECLA DE DIVISION (KeyDown|KeyHold) +0:1032:2:38:5 //Previous instrument: Ctrl+FLECHA ARRIBA (KeyDown|KeyHold) +0:1033:2:106:5 //Next instrument: Ctrl+TECLA DE MULTIPLICACION (KeyDown|KeyHold) +0:1033:2:40:5 //Next instrument: Ctrl+FLECHA ABAJO (KeyDown|KeyHold) +0:1036:0:111:1 //Previous octave: TECLA DE DIVISION (KeyDown) +0:1037:0:106:1 //Next octave: TECLA DE MULTIPLICACION (KeyDown) +0:1034:2:37:5 //Previous order: Ctrl+FLECHA IZQUIERDA (KeyDown|KeyHold) +0:1035:2:39:5 //Next order: Ctrl+FLECHA DERECHA (KeyDown|KeyHold) + +//----( General Context [bottom] (1) )------------ + +//----( Pattern Context [bottom] (2) )------------ +2:1017:0:34:5 //Jump down by measure: AV PAG (KeyDown|KeyHold) +2:1018:0:33:5 //Jump up by measure: RE PAG (KeyDown|KeyHold) +2:1338:4:34:5 //Jump down by beat: Alt+AV PAG (KeyDown|KeyHold) +2:1339:4:33:5 //Jump up by beat: Alt+RE PAG (KeyDown|KeyHold) +2:1340:6:34:5 //Snap down to beat: Ctrl+Alt+AV PAG (KeyDown|KeyHold) +2:1341:6:33:5 //Snap up to beat: Ctrl+Alt+RE PAG (KeyDown|KeyHold) +2:1038:0:40:5 //Navigate down by 1 row: FLECHA ABAJO (KeyDown|KeyHold) +2:1039:0:38:5 //Navigate up by 1 row: FLECHA ARRIBA (KeyDown|KeyHold) +2:1691:4:40:5 //Navigate down by spacing: Alt+FLECHA ABAJO (KeyDown|KeyHold) +2:1692:4:38:5 //Navigate up by spacing: Alt+FLECHA ARRIBA (KeyDown|KeyHold) +2:1040:0:37:5 //Navigate left: FLECHA IZQUIERDA (KeyDown|KeyHold) +2:1041:0:39:5 //Navigate right: FLECHA DERECHA (KeyDown|KeyHold) +2:1042:0:9:5 //Navigate to next channel: TABULACION (KeyDown|KeyHold) +2:1043:1:9:5 //Navigate to previous channel: Shift+TABULACION (KeyDown|KeyHold) +2:1044:0:36:1 //Go to first channel: INICIO (KeyDown) +2:1045:2:36:1 //Go to first row: Ctrl+INICIO (KeyDown) +2:1046:6:36:1 //Go to first row of first channel: Ctrl+Alt+INICIO (KeyDown) +2:1047:0:35:1 //Go to last channel: FIN (KeyDown) +2:1048:2:35:1 //Go to last row: Ctrl+FIN (KeyDown) +2:1049:6:35:1 //Go to last row of last channel: Ctrl+Alt+FIN (KeyDown) +2:1050:1:16:1 //Selection key: Shift+MAYUSCULAS (KeyDown) +2:1051:2:17:1 //Copy select key: Ctrl (KeyDown) +2:1011:2:76:1 //Select channel / Select all: Ctrl+L (KeyDown) +2:1663:0:122:1 //Toggle follow song: F11 (KeyDown) +2:1003:0:13:1 //Quick copy: ENTRAR (KeyDown) +2:1004:0:32:5 //Quick paste: BARRA ESPACIADORA (KeyDown|KeyHold) +2:1001:2:32:1 //Enable recording: Ctrl+BARRA ESPACIADORA (KeyDown) +2:1002:2:13:5 //Play row: Ctrl+ENTRAR (KeyDown|KeyHold) +2:1317:4:18:1 //Set row jump on note entry: Alt (KeyDown) +2:1685:2:9:1 //Switch to order list: Ctrl+TABULACION (KeyDown) +2:1806:2:68:1 //Duplicate pattern: Ctrl+D (KeyDown) +2:1836:2:191:1 //Edit plugin assigned to PC note: Ctrl+} (KeyDown) +2:1662:6:80:1 //Toggle channel's plugin editor: Ctrl+Alt+P (KeyDown) +2:1062:0:93:1 //Show note properties: APLICACI\xD3N (KeyDown) +2:1772:5:80:1 //Show pattern properties window: Shift+Alt+P (KeyDown) +2:1819:2:69:1 //Split Keyboard Settings dialog: Ctrl+E (KeyDown) +2:1776:1:122:1 //Toggle loop pattern: Shift+F11 (KeyDown) +2:1780:2:84:1 //Show playback time at current row: Ctrl+T (KeyDown) +2:1005:0:121:1 //Mute current channel: F10 (KeyDown) +2:1006:2:121:1 //Solo current channel: Ctrl+F10 (KeyDown) +2:1771:6:121:1 //Unmute all channels: Ctrl+Alt+F10 (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) +2:1009:3:81:5 //Transpose +12: Shift+Ctrl+Q (KeyDown|KeyHold) +2:1010:3:65:5 //Transpose -12: Shift+Ctrl+A (KeyDown|KeyHold) +2:1012:2:77:1 //Amplify selection: Ctrl+M (KeyDown) +2:1014:2:74:1 //Interpolate volume: Ctrl+J (KeyDown) +2:1015:2:75:1 //Interpolate effect: Ctrl+K (KeyDown) +2:1016:4:66:1 //Open effect visualizer: Alt+B (KeyDown) +2:1766:2:71:1 //Go to row/channel/...: Ctrl+G (KeyDown) +2:1013:2:73:1 //Apply current instrument: Ctrl+I (KeyDown) +2:1660:4:69:5 //Grow selection: Alt+E (KeyDown|KeyHold) +2:1661:4:68:5 //Shrink selection: Alt+D (KeyDown|KeyHold) +2:1058:0:46:1 //Clear field: SUPR (KeyDown) +2:1664:1:190:1 //Clear field (IT Style): Shift+. (KeyDown) +2:1059:2:46:5 //Clear row and step: Ctrl+SUPR (KeyDown|KeyHold) +2:1665:1:46:5 //Clear field and step (IT Style): Shift+SUPR (KeyDown|KeyHold) +2:1061:0:8:5 //Delete rows: RETROCESO (KeyDown|KeyHold) +2:1377:2:8:5 //Delete all rows: Ctrl+RETROCESO (KeyDown|KeyHold) +2:1378:0:45:5 //Insert Row: INSERT (KeyDown|KeyHold) +2:1379:2:45:5 //Insert All Rows: Ctrl+INSERT (KeyDown|KeyHold) +2:1055:0:109:5 //Previous pattern: TECLA DE SUSTRACCION (KeyDown|KeyHold) +2:1054:0:107:5 //Next pattern: TECLA DE ADICION (KeyDown|KeyHold) + +//----( Pattern Context [bottom] - Note Col (3) )------------ +3:1064:0:90:1 //Base octave C: Z (KeyDown) +3:1065:0:83:1 //Base octave C#: S (KeyDown) +3:1066:0:88:1 //Base octave D: X (KeyDown) +3:1067:0:68:1 //Base octave D#: D (KeyDown) +3:1068:0:67:1 //Base octave E: C (KeyDown) +3:1069:0:86:1 //Base octave F: V (KeyDown) +3:1070:0:71:1 //Base octave F#: G (KeyDown) +3:1071:0:66:1 //Base octave G: B (KeyDown) +3:1072:0:72:1 //Base octave G#: H (KeyDown) +3:1073:0:78:1 //Base octave A: N (KeyDown) +3:1074:0:74:1 //Base octave A#: J (KeyDown) +3:1075:0:77:1 //Base octave B: M (KeyDown) +3:1076:0:81:1 //Base octave +1 C: Q (KeyDown) +3:1076:0:188:1 //Base octave +1 C: , (KeyDown) +3:1077:0:50:1 //Base octave +1 C#: 2 (KeyDown) +3:1077:0:76:1 //Base octave +1 C#: L (KeyDown) +3:1078:0:87:1 //Base octave +1 D: W (KeyDown) +3:1078:0:190:1 //Base octave +1 D: . (KeyDown) +3:1079:0:51:1 //Base octave +1 D#: 3 (KeyDown) +3:1079:0:192:1 //Base octave +1 D#: \xF1 (KeyDown) +3:1080:0:69:1 //Base octave +1 E: E (KeyDown) +3:1080:0:189:1 //Base octave +1 E: - (KeyDown) +3:1081:0:82:1 //Base octave +1 F: R (KeyDown) +3:1082:0:53:1 //Base octave +1 F#: 5 (KeyDown) +3:1083:0:84:1 //Base octave +1 G: T (KeyDown) +3:1084:0:54:1 //Base octave +1 G#: 6 (KeyDown) +3:1085:0:89:1 //Base octave +1 A: Y (KeyDown) +3:1086:0:55:1 //Base octave +1 A#: 7 (KeyDown) +3:1087:0:85:1 //Base octave +1 B: U (KeyDown) +3:1088:0:73:1 //Base octave +2 C: I (KeyDown) +3:1089:0:57:1 //Base octave +2 C#: 9 (KeyDown) +3:1090:0:79:1 //Base octave +2 D: O (KeyDown) +3:1091:0:48:1 //Base octave +2 D#: 0 (KeyDown) +3:1092:0:80:1 //Base octave +2 E: P (KeyDown) +3:1212:0:96:1 //Set octave 0: NUMERO 0 (KeyDown) +3:1213:0:97:1 //Set octave 1: NUMERO 1 (KeyDown) +3:1214:0:98:1 //Set octave 2: NUMERO 2 (KeyDown) +3:1215:0:99:1 //Set octave 3: NUMERO 3 (KeyDown) +3:1216:0:100:1 //Set octave 4: NUMERO 4 (KeyDown) +3:1217:0:101:1 //Set octave 5: NUMERO 5 (KeyDown) +3:1218:0:102:1 //Set octave 6: NUMERO 6 (KeyDown) +3:1219:0:103:1 //Set octave 7: NUMERO 7 (KeyDown) +3:1220:0:104:1 //Set octave 8: NUMERO 8 (KeyDown) +3:1221:0:105:1 //Set octave 9: NUMERO 9 (KeyDown) +3:1316:1:16:1 //Chord Modifier: Shift+MAYUSCULAS (KeyDown) +3:1200:0:220:1 //Note Cut: | (KeyDown) +3:1201:0:221:1 //Note Off: \xBF (KeyDown) +3:1791:1:221:1 //Note Fade: Shift+\xBF (KeyDown) +3:1788:1:219:1 //Parameter control(MPTm only): Shift+' (KeyDown) +3:1789:0:219:1 //Parameter control(smooth)(MPTm only): ' (KeyDown) + +//----( Pattern Context [bottom] - Ins Col (4) )------------ +4:1202:0:96:1 //Set instrument digit 0: NUMERO 0 (KeyDown) +4:1202:0:48:1 //Set instrument digit 0: 0 (KeyDown) +4:1203:0:97:1 //Set instrument digit 1: NUMERO 1 (KeyDown) +4:1203:0:49:1 //Set instrument digit 1: 1 (KeyDown) +4:1204:0:98:1 //Set instrument digit 2: NUMERO 2 (KeyDown) +4:1204:0:50:1 //Set instrument digit 2: 2 (KeyDown) +4:1205:0:99:1 //Set instrument digit 3: NUMERO 3 (KeyDown) +4:1205:0:51:1 //Set instrument digit 3: 3 (KeyDown) +4:1206:0:100:1 //Set instrument digit 4: NUMERO 4 (KeyDown) +4:1206:0:52:1 //Set instrument digit 4: 4 (KeyDown) +4:1207:0:101:1 //Set instrument digit 5: NUMERO 5 (KeyDown) +4:1207:0:53:1 //Set instrument digit 5: 5 (KeyDown) +4:1208:0:102:1 //Set instrument digit 6: NUMERO 6 (KeyDown) +4:1208:0:54:1 //Set instrument digit 6: 6 (KeyDown) +4:1209:0:103:1 //Set instrument digit 7: NUMERO 7 (KeyDown) +4:1209:0:55:1 //Set instrument digit 7: 7 (KeyDown) +4:1210:0:104:1 //Set instrument digit 8: NUMERO 8 (KeyDown) +4:1210:0:56:1 //Set instrument digit 8: 8 (KeyDown) +4:1211:0:105:1 //Set instrument digit 9: NUMERO 9 (KeyDown) +4:1211:0:57:1 //Set instrument digit 9: 9 (KeyDown) + +//----( Pattern Context [bottom] - Vol Col (5) )------------ +5:1222:0:48:1 //Set volume digit 0: 0 (KeyDown) +5:1222:0:96:1 //Set volume digit 0: NUMERO 0 (KeyDown) +5:1223:0:49:1 //Set volume digit 1: 1 (KeyDown) +5:1223:0:97:1 //Set volume digit 1: NUMERO 1 (KeyDown) +5:1224:0:50:1 //Set volume digit 2: 2 (KeyDown) +5:1224:0:98:1 //Set volume digit 2: NUMERO 2 (KeyDown) +5:1225:0:51:1 //Set volume digit 3: 3 (KeyDown) +5:1225:0:99:1 //Set volume digit 3: NUMERO 3 (KeyDown) +5:1226:0:52:1 //Set volume digit 4: 4 (KeyDown) +5:1226:0:100:1 //Set volume digit 4: NUMERO 4 (KeyDown) +5:1227:0:53:1 //Set volume digit 5: 5 (KeyDown) +5:1227:0:101:1 //Set volume digit 5: NUMERO 5 (KeyDown) +5:1228:0:54:1 //Set volume digit 6: 6 (KeyDown) +5:1228:0:102:1 //Set volume digit 6: NUMERO 6 (KeyDown) +5:1229:0:55:1 //Set volume digit 7: 7 (KeyDown) +5:1229:0:103:1 //Set volume digit 7: NUMERO 7 (KeyDown) +5:1230:0:56:1 //Set volume digit 8: 8 (KeyDown) +5:1230:0:104:1 //Set volume digit 8: NUMERO 8 (KeyDown) +5:1231:0:57:1 //Set volume digit 9: 9 (KeyDown) +5:1231:0:105:1 //Set volume digit 9: NUMERO 9 (KeyDown) +5:1232:0:86:1 //Vol command - volume: V (KeyDown) +5:1233:0:80:1 //Vol command - pan: P (KeyDown) +5:1234:0:67:1 //Vol command - vol slide up: C (KeyDown) +5:1235:0:68:1 //Vol command - vol slide down: D (KeyDown) +5:1236:0:65:1 //Vol command - vol fine slide up: A (KeyDown) +5:1237:0:66:1 //Vol command - vol fine slide down: B (KeyDown) +5:1238:0:85:1 //Vol command - vibrato speed: U (KeyDown) +5:1239:0:72:1 //Vol command - vibrato: H (KeyDown) +5:1240:0:76:1 //Vol command - XM pan left: L (KeyDown) +5:1241:0:82:1 //Vol command - XM pan right: R (KeyDown) +5:1242:0:71:1 //Vol command - Portamento: G (KeyDown) +5:1243:0:70:1 //Vol command - Portamento Up: F (KeyDown) +5:1244:0:69:1 //Vol command - Portamento Down: E (KeyDown) +5:1246:0:79:1 //Vol command - Offset: O (KeyDown) + +//----( Pattern Context [bottom] - FX Col (6) )------------ +6:1294:0:226:1 //FX midi macro slide: < (KeyDown) +6:1295:1:192:1 //FX combined note delay and note cut: Shift+\xF1 (KeyDown) +6:1295:0:186:1 //FX combined note delay and note cut: AGUDO (KeyDown) +6:1666:0:189:1 //FX parameter extension command: - (KeyDown) + +//----( Pattern Context [bottom] - Param Col (7) )------------ +7:1247:0:48:1 //FX Param digit 0: 0 (KeyDown) +7:1247:0:96:1 //FX Param digit 0: NUMERO 0 (KeyDown) +7:1248:0:49:1 //FX Param digit 1: 1 (KeyDown) +7:1248:0:97:1 //FX Param digit 1: NUMERO 1 (KeyDown) +7:1249:0:50:1 //FX Param digit 2: 2 (KeyDown) +7:1249:0:98:1 //FX Param digit 2: NUMERO 2 (KeyDown) +7:1250:0:51:1 //FX Param digit 3: 3 (KeyDown) +7:1250:0:99:1 //FX Param digit 3: NUMERO 3 (KeyDown) +7:1251:0:52:1 //FX Param digit 4: 4 (KeyDown) +7:1251:0:100:1 //FX Param digit 4: NUMERO 4 (KeyDown) +7:1252:0:53:1 //FX Param digit 5: 5 (KeyDown) +7:1252:0:101:1 //FX Param digit 5: NUMERO 5 (KeyDown) +7:1253:0:54:1 //FX Param digit 6: 6 (KeyDown) +7:1253:0:102:1 //FX Param digit 6: NUMERO 6 (KeyDown) +7:1254:0:55:1 //FX Param digit 7: 7 (KeyDown) +7:1254:0:103:1 //FX Param digit 7: NUMERO 7 (KeyDown) +7:1255:0:56:1 //FX Param digit 8: 8 (KeyDown) +7:1255:0:104:1 //FX Param digit 8: NUMERO 8 (KeyDown) +7:1256:0:57:1 //FX Param digit 9: 9 (KeyDown) +7:1256:0:105:1 //FX Param digit 9: NUMERO 9 (KeyDown) +7:1257:0:65:1 //FX Param digit A: A (KeyDown) +7:1258:0:66:1 //FX Param digit B: B (KeyDown) +7:1259:0:67:1 //FX Param digit C: C (KeyDown) +7:1260:0:68:1 //FX Param digit D: D (KeyDown) +7:1261:0:69:1 //FX Param digit E: E (KeyDown) +7:1262:0:70:1 //FX Param digit F: F (KeyDown) + +//----( Sample Context [bottom] (8) )------------ +8:1380:2:84:1 //Trim sample around loop points: Ctrl+T (KeyDown) +8:1383:0:8:1 //Silence sample selection: RETROCESO (KeyDown) +8:1384:1:78:1 //Normalise Sample: Shift+N (KeyDown) +8:1385:3:65:1 //Amplify Sample: Shift+Ctrl+A (KeyDown) +8:1385:2:77:1 //Amplify Sample: Ctrl+M (KeyDown) +8:1381:3:82:1 //Reverse sample: Shift+Ctrl+R (KeyDown) +8:1382:0:46:1 //Delete sample selection: SUPR (KeyDown) +8:1386:0:107:1 //Zoom Out: TECLA DE ADICION (KeyDown) +8:1387:0:109:1 //Zoom In: TECLA DE SUSTRACCION (KeyDown) +8:1784:2:73:1 //Invert sample phase: Ctrl+I (KeyDown) +8:1785:2:85:1 //Signed/Unsigned conversion: Ctrl+U (KeyDown) +8:1790:2:69:1 //Remove DC Offset: Ctrl+E (KeyDown) +8:1856:2:68:1 //Quick fade: Ctrl+D (KeyDown) +8:1857:2:76:1 //Crossfade sample loop: Ctrl+L (KeyDown) + +//----( Instrument Context [bottom] (9) )------------ +9:1837:0:107:5 //Zoom In: TECLA DE ADICION (KeyDown|KeyHold) +9:1838:0:109:5 //Zoom Out: TECLA DE SUSTRACCION (KeyDown|KeyHold) +9:1825:1:9:5 //Select previous envelope point: Shift+TABULACION (KeyDown|KeyHold) +9:1826:0:9:5 //Select next envelope point: TABULACION (KeyDown|KeyHold) +9:1821:0:37:5 //Move envelope point left: FLECHA IZQUIERDA (KeyDown|KeyHold) +9:1822:0:39:5 //Move envelope point right: FLECHA DERECHA (KeyDown|KeyHold) +9:1823:0:38:5 //Move envelope point up: FLECHA ARRIBA (KeyDown|KeyHold) +9:1834:0:33:5 //Move envelope point up (big step): RE PAG (KeyDown|KeyHold) +9:1824:0:40:5 //Move envelope point down: FLECHA ABAJO (KeyDown|KeyHold) +9:1835:0:34:5 //Move envelope point down (big step): AV PAG (KeyDown|KeyHold) +9:1827:0:45:1 //Insert envelope point: INSERT (KeyDown) +9:1828:0:46:1 //Remove envelope point: SUPR (KeyDown) +9:1828:0:8:1 //Remove envelope point: RETROCESO (KeyDown) +9:1829:0:36:1 //Set loop start: INICIO (KeyDown) +9:1830:0:35:1 //Set loop end: FIN (KeyDown) +9:1831:2:36:1 //Set sustain loop start: Ctrl+INICIO (KeyDown) +9:1832:2:35:1 //Set sustain loop end: Ctrl+FIN (KeyDown) +9:1833:2:82:1 //Toggle release node: Ctrl+R (KeyDown) + +//----( Comments Context [bottom] (10) )------------ + +//----( Unknown Context (11) )------------ + +//----( Unknown Context (12) )------------ + +//----( Plugin GUI Context (13) )------------ +13:1763:0:109:5 //Previous plugin preset: TECLA DE SUSTRACCION (KeyDown|KeyHold) +13:1764:0:107:5 //Next plugin preset: TECLA DE ADICION (KeyDown|KeyHold) +13:1782:2:109:5 //Plugin preset backward jump: Ctrl+TECLA DE SUSTRACCION (KeyDown|KeyHold) +13:1783:2:107:5 //Plugin preset forward jump: Ctrl+TECLA DE ADICION (KeyDown|KeyHold) +13:1765:3:68:1 //Randomize plugin parameters: Shift+Ctrl+D (KeyDown) +13:1839:2:82:1 //Toggle parameter recording: Ctrl+R (KeyDown) +13:1840:2:75:1 //Pass key presses to plugin: Ctrl+K (KeyDown) +13:1841:2:66:1 //Bypass plugin: Ctrl+B (KeyDown) + +//----( General Context [top] (14) )------------ + +//----( Pattern Context [top] (15) )------------ + +//----( 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) )------------ + +//----( Orderlist (19) )------------ +19:1802:0:46:5 //Delete Order: SUPR (KeyDown|KeyHold) +19:1803:0:45:5 //Insert Order: INSERT (KeyDown|KeyHold) +19:1804:0:13:5 //Edit Pattern: ENTRAR (KeyDown|KeyHold) +19:1805:0:9:5 //Switch to pattern editor: TABULACION (KeyDown|KeyHold) +19:1794:0:37:5 //Previous Order: FLECHA IZQUIERDA (KeyDown|KeyHold) +19:1794:0:38:5 //Previous Order: FLECHA ARRIBA (KeyDown|KeyHold) +19:1795:0:39:5 //Next Order: FLECHA DERECHA (KeyDown|KeyHold) +19:1795:0:40:5 //Next Order: FLECHA ABAJO (KeyDown|KeyHold) +19:1796:0:36:5 //First Order: INICIO (KeyDown|KeyHold) +19:1797:0:35:5 //Last Order: FIN (KeyDown|KeyHold) +19:1807:0:48:5 //Pattern index digit 0: 0 (KeyDown|KeyHold) +19:1807:0:96:5 //Pattern index digit 0: NUMERO 0 (KeyDown|KeyHold) +19:1808:0:49:5 //Pattern index digit 1: 1 (KeyDown|KeyHold) +19:1808:0:97:5 //Pattern index digit 1: NUMERO 1 (KeyDown|KeyHold) +19:1809:0:50:5 //Pattern index digit 2: 2 (KeyDown|KeyHold) +19:1809:0:98:5 //Pattern index digit 2: NUMERO 2 (KeyDown|KeyHold) +19:1810:0:51:5 //Pattern index digit 3: 3 (KeyDown|KeyHold) +19:1810:0:99:5 //Pattern index digit 3: NUMERO 3 (KeyDown|KeyHold) +19:1811:0:52:5 //Pattern index digit 4: 4 (KeyDown|KeyHold) +19:1811:0:100:5 //Pattern index digit 4: NUMERO 4 (KeyDown|KeyHold) +19:1812:0:53:5 //Pattern index digit 5: 5 (KeyDown|KeyHold) +19:1812:0:101:5 //Pattern index digit 5: NUMERO 5 (KeyDown|KeyHold) +19:1813:0:54:5 //Pattern index digit 6: 6 (KeyDown|KeyHold) +19:1813:0:102:5 //Pattern index digit 6: NUMERO 6 (KeyDown|KeyHold) +19:1814:0:55:5 //Pattern index digit 7: 7 (KeyDown|KeyHold) +19:1814:0:103:5 //Pattern index digit 7: NUMERO 7 (KeyDown|KeyHold) +19:1815:0:56:5 //Pattern index digit 8: 8 (KeyDown|KeyHold) +19:1815:0:104:5 //Pattern index digit 8: NUMERO 8 (KeyDown|KeyHold) +19:1816:0:57:5 //Pattern index digit 9: 9 (KeyDown|KeyHold) +19:1816:0:105:5 //Pattern index digit 9: NUMERO 9 (KeyDown|KeyHold) +19:1817:0:107:5 //Increase pattern index : TECLA DE ADICION (KeyDown|KeyHold) +19:1817:0:187:5 //Increase pattern index : + (KeyDown|KeyHold) +19:1818:0:109:5 //Decrease pattern index: TECLA DE SUSTRACCION (KeyDown|KeyHold) +19:1818:0:189:5 //Decrease pattern index: - (KeyDown|KeyHold) Added: trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_mpt_jmkz.mkb =================================================================== --- trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_mpt_jmkz.mkb (rev 0) +++ trunk/OpenMPT/packageTemplate/extraKeymaps/es-LA_mpt_jmkz.mkb 2011-04-01 14:59:06 UTC (rev 834) @@ -0,0 +1,377 @@ +//-------- OpenMPT key binding definition file ------- +//-Format is: - +//- Context:Command ID:Modifiers:Key:KeypressEventType //Comments - +//---------------------------------------------------------------------- +version:1 + +//----( Global Context (0) )------------ +0:1347:2:78:1 //File/New: Ctrl+N (KeyDown) +0:1346:2:79:1 //File/Open: Ctrl+O (KeyDown) +0:1349:2:83:1 //File/Save: Ctrl+S (KeyDown) +0:1350:3:83:1 //File/Save As: Shift+Ctrl+S (KeyDown) +0:1030:0:116:1 //Play song/Pause song: F5 (KeyDown) +0:1031:0:119:1 //Pause song: F8 (KeyDown) +0:1375:0:27:1 //Stop Song: ESC (KeyDown) +0:1029:0:117:1 //Play song from start: F6 (KeyDown) +0:1027:0:118:1 //Play pattern from start: F7 (KeyDown) +0:1026:2:118:1 //Play pattern from cursor: Ctrl+F7 (KeyDown) +0:1376:0:120:1 //Toggle Midi Record: F9 (KeyDown) +0:1359:2:90:1 //Undo: Ctrl+Z (KeyDown) +0:1360:2:88:1 //Cut: Ctrl+X (KeyDown) +0:1361:2:67:1 //Copy: Ctrl+C (KeyDown) +0:1362:2:86:1 //Paste: Ctrl+V (KeyDown) +0:1362:1:45:1 //Paste: Shift+INSERT (KeyDown) +0:1363:3:86:1 //Mix Paste: Shift+Ctrl+V (KeyDown) +0:1793:1:86:5 //Paste Flood: Shift+V (KeyDown|KeyHold) +0:1820:6:86:1 //Push Forward Paste: Ctrl+Alt+V (KeyDown) +0:1364:2:53:1 //SelectAll: Ctrl+5 (KeyDown) +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:1022:4:80:1 //View Pattern: Alt+P (KeyDown) +0:1023:4:83:1 //View Samples: Alt+S (KeyDown) +0:1024:4:78:1 //View Instruments: Alt+N (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:1032:2:111:5 //Previous instrument: Ctrl+TECLA DE DIVISION (KeyDown|KeyHold) +0:1032:2:38:5 //Previous instrument: Ctrl+FLECHA ARRIBA (KeyDown|KeyHold) +0:1033:2:106:5 //Next instrument: Ctrl+TECLA DE MULTIPLICACION (KeyDown|KeyHold) +0:1033:2:40:5 //Next instrument: Ctrl+FLECHA ABAJO (KeyDown|KeyHold) +0:1036:0:111:1 //Previous octave: TECLA DE DIVISION (KeyDown) +0:1037:0:106:1 //Next octave: TECLA DE MULTIPLICACION (KeyDown) +0:1034:2:37:5 //Previous order: Ctrl+FLECHA IZQUIERDA (KeyDown|KeyHold) +0:1035:2:39:5 //Next order: Ctrl+FLECHA DERECHA (KeyDown|KeyHold) + +//----( General Context [bottom] (1) )------------ + +//----( Pattern Context [bottom] (2) )------------ +2:1017:0:34:5 //Jump down by measure: AV PAG (KeyDown|KeyHold) +2:1018:0:33:5 //Jump up by measure: RE PAG (KeyDown|KeyHold) +2:1338:4:34:5 //Jump down by beat: Alt+AV PAG (KeyDown|KeyHold) +2:1339:4:33:5 //Jump up by beat: Alt+RE PAG (KeyDown|KeyHold) +2:1340:6:34:5 //Snap down to beat: Ctrl+Alt+AV PAG (KeyDown|KeyHold) +2:1341:6:33:5 //Snap up to beat: Ctrl+Alt+RE PAG (KeyDown|KeyHold) +2:1038:0:40:5 //Navigate down by 1 row: FLECHA ABAJO (KeyDown|KeyHold) +2:1039:0:38:5 //Navigate up by 1 row: FLECHA ARRIBA (KeyDown|KeyHold) +2:1691:4:40:5 //Navigate down by spacing: Alt+FLECHA ABAJO (KeyDown|KeyHold) +2:1692:4:38:5 //Navigate up by spacing: Alt+FLECHA ARRIBA (KeyDown|KeyHold) +2:1040:0:37:5 //Navigate left: FLECHA IZQUIERDA (KeyDown|KeyHold) +2:1041:0:39:5 //Navigate right: FLECHA DERECHA (KeyDown|KeyHold) +2:1042:0:9:5 //Navigate to next channel: TABULACION (KeyDown|KeyHold) +2:1043:1:9:5 //Navigate to previous channel: Shift+TABULACION (KeyDown|KeyHold) +2:1044:0:36:1 //Go to first channel: INICIO (KeyDown) +2:1045:2:36:1 //Go to first row: Ctrl+INICIO (KeyDown) +2:1046:6:36:1 //Go to first row of first channel: Ctrl+Alt+INICIO (KeyDown) +2:1047:0:35:1 //Go to last channel: FIN (KeyDown) +2:1048:2:35:1 //Go to last row: Ctrl+FIN (KeyDown) +2:1049:6:35:1 //Go to last row of last channel: Ctrl+Alt+FIN (KeyDown) +2:1050:1:16:1 //Selection key: Shift+MAYUSCULAS (KeyDown) +2:1051:2:17:1 //Copy select key: Ctrl (KeyDown) +2:1011:2:76:1 //Select channel / Select all: Ctrl+L (KeyDown) +2:1663:0:122:1 //Toggle follow song: F11 (KeyDown) +2:1003:0:13:1 //Quick copy: ENTRAR (KeyDown) +2:1004:0:32:5 //Quick paste: BARRA ESPACIADORA (KeyDown|KeyHold) +2:1001:2:32:1 //Enable recording: Ctrl+BARRA ESPACIADORA (KeyDown) +2:1002:2:13:5 //Play row: Ctrl+ENTRAR (KeyDown|KeyHold) +2:1317:4:18:1 //Set row jump on note entry: Alt (KeyDown) +2:1685:2:9:1 //Switch to order list: Ctrl+TABULACION (KeyDown) +2:1806:2:68:1 //Duplicate pattern: Ctrl+D (KeyDown) +2:1836:2:191:1 //Edit plugin assigned to PC note: Ctrl+} (KeyDown) +2:1662:6:80:1 //Toggle channel's plugin editor: Ctrl+Alt+P (KeyDown) +2:1062:0:93:1 //Show note properties: APLICACI\xD3N (KeyDown) +2:1772:5:80:1 //Show pattern properties window: Shift+Alt+P (KeyDown) +2:1819:2:69:1 //Split Keyboard Settings dialog: Ctrl+E (KeyDown) +2:1776:1:122:1 //Toggle loop pattern: Shift+F11 (KeyDown) +2:1780:2:84:1 //Show playback time at current row: Ctrl+T (KeyDown) +2:1005:0:121:1 //Mute current channel: F10 (KeyDown) +2:1006:2:121:1 //Solo current channel: Ctrl+F10 (KeyDown) +2:1771:6:121:1 //Unmute all channels: Ctrl+Alt+F10 (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) +2:1009:3:81:5 //Transpose +12: Shift+Ctrl+Q (KeyDown|KeyHold) +2:1010:3:65:5 //Transpose -12: Shift+Ctrl+A (KeyDown|KeyHold) +2:1012:2:77:1 //Amplify selection: Ctrl+M (KeyDown) +2:1014:2:74:1 //Interpolate volume: Ctrl+J (KeyDown) +2:1015:2:75:1 //Interpolate effect: Ctrl+K (KeyDown) +2:1016:4:66:1 //Open effect visualizer: Alt+B (KeyDown) +2:1766:2:71:1 //Go to row/channel/...: Ctrl+G (KeyDown) +2:1013:2:73:1 //Apply current instrument: Ctrl+I (KeyDown) +2:1660:4:69:5 //Grow selection: Alt+E (KeyDown|KeyHold) +2:1661:4:68:5 //Shrink selection: Alt+D (KeyDown|KeyHold) +2:1058:0:46:1 //Clear field: SUPR (KeyDown) +2:1664:1:190:1 //Clear field (IT Style): Shift+. (KeyDown) +2:1059:2:46:5 //Clear row and step: Ctrl+SUPR (KeyDown|KeyHold) +2:1665:1:46:5 //Clear field and step (IT Style): Shift+SUPR (KeyDown|KeyHold) +2:1061:0:8:5 //Delete rows: RETROCESO (KeyDown|KeyHold) +2:1377:2:8:5 //Delete all rows: Ctrl+RETROCESO (KeyDown|KeyHold) +2:1378:0:45:5 //Insert Row: INSERT (KeyDown|KeyHold) +2:1379:2:45:5 //Insert All Rows: Ctrl+INSERT (KeyDown|KeyHold) +2:1055:0:109:5 //Previous pattern: TECLA DE SUSTRACCION (KeyDown|KeyHold) +2:1054:0:107:5 //Next pattern: TECLA DE ADICION (KeyDown|KeyHold) + +//----( Pattern Context [bottom] - Note Col (3) )------------ +3:1064:0:81:1 //Base octave C: Q (KeyDown) +3:1065:0:87:1 //Base octave C#: W (KeyDown) +3:1066:0:69:1 //Base octave D: E (KeyDown) +3:1067:0:82:1 //Base octave D#: R (KeyDown) +3:1068:0:84:1 //Base octave E: T (KeyDown) +3:1069:0:89:1 //Base octave F: Y (KeyDown) +3:1070:0:85:1 //Base octave F#: U (KeyDown) +3:1071:0:73:1 //Base octave G: I (KeyDown) +3:1072:0:79:1 //Base octave G#: O (KeyDown) +3:1073:0:80:1 //Base octave A: P (KeyDown) +3:1074:0:186:1 //Base octave A#: AGUDO (KeyDown) +3:1075:0:187:1 //Base octave B: + (KeyDown) +3:1076:0:65:1 //Base octave +1 C: A (KeyDown) +3:1077:0:83:1 //Base octave +1 C#: S (KeyDown) +3:1078:0:68:1 //Base octave +1 D: D (KeyDown) +3:1079:0:70:1 //Base octave +1 D#: F (KeyDown) +3:1080:0:71:1 //Base octave +1 E: G (KeyDown) +3:1081:0:72:1 //Base octave +1 F: H (KeyDown) +3:1082:0:74:1 //Base octave +1 F#: J (KeyDown) +3:1083:0:75:1 //Base octave +1 G: K (KeyDown) +3:1084:0:76:1 //Base octave +1 G#: L (KeyDown) +3:1085:0:192:1 //Base octave +1 A: \xF1 (KeyDown) +3:1086:0:222:1 //Base octave +1 A#: { (KeyDown) +3:1087:0:191:1 //Base octave +1 B: } (KeyDown) +3:1088:0:90:1 //Base octave +2 C: Z (KeyDown) +3:1089:0:88:1 //Base octave +2 C#: X (KeyDown) +3:1090:0:67:1 //Base octave +2 D: C (KeyDown) +3:1091:0:86:1 //Base octave +2 D#: V (KeyDown) +3:1092:0:66:1 //Base octave +2 E: B (KeyDown) +3:1093:0:78:1 //Base octave +2 F: N (KeyDown) +3:1094:0:77:1 //Base octave +2 F#: M (KeyDown) +3:1095:0:188:1 //Base octave +2 G: , (KeyDown) +3:1096:0:190:1 //Base octave +2 G#: . (KeyDown) +3:1097:0:189:1 //Base octave +2 A: - (KeyDown) +3:1212:0:48:1 //Set octave 0: 0 (KeyDown) +3:1212:0:96:1 //Set octave 0: NUMERO 0 (KeyDown) +3:1213:0:49:1 //Set octave 1: 1 (KeyDown) +3:1213:0:97:1 //Set octave 1: NUMERO 1 (KeyDown) +3:1214:0:50:1 //Set octave 2: 2 (KeyDown) +3:1214:0:98:1 //Set octave 2: NUMERO 2 (KeyDown) +3:1215:0:51:1 //Set octave 3: 3 (KeyDown) +3:1215:0:99:1 //Set octave 3: NUMERO 3 (KeyDown) +3:1216:0:52:1 //Set octave 4: 4 (KeyDown) +3:1216:0:100:1 //Set octave 4: NUMERO 4 (KeyDown) +3:1217:0:53:1 //Set octave 5: 5 (KeyDown) +3:1217:0:101:1 //Set octave 5: NUMERO 5 (KeyDown) +3:1218:0:54:1 //Set octave 6: 6 (KeyDown) +3:1218:0:102:1 //Set octave 6: NUMERO 6 (KeyDown) +3:1219:0:55:1 //Set octave 7: 7 (KeyDown) +3:1219:0:103:1 //Set octave 7: NUMERO 7 (KeyDown) +3:1220:0:56:1 //Set octave 8: 8 (KeyDown) +3:1220:0:104:1 //Set octave 8: NUMERO 8 (KeyDown) +3:1221:0:57:1 //Set octave 9: 9 (KeyDown) +3:1221:0:105:1 //Set octave 9: NUMERO 9 (KeyDown) +3:1316:1:16:1 //Chord Modifier: Shift+MAYUSCULAS (KeyDown) +3:1200:0:220:1 //Note Cut: | (KeyDown) +3:1201:0:221:1 //Note Off: \xBF (KeyDown) +3:1791:1:221:1 //Note Fade: Shift+\xBF (KeyDown) +3:1788:1:219:1 //Parameter control(MPTm only): Shift+' (KeyDown) +3:1789:0:219:1 //Parameter control(smooth)(MPTm only): ' (KeyDown) + +//----( Pattern Context [bottom] - Ins Col (4) )------------ +4:1202:0:96:1 //Set instrument digit 0: NUMERO 0 (KeyDown) +4:1202:0:48:1 //Set instrument digit 0: 0 (KeyDown) +4:1203:0:97:1 //Set instrument digit 1: NUMERO 1 (KeyDown) +4:1203:0:49:1 //Set instrument digit 1: 1 (KeyDown) +4:1204:0:98:1 //Set instrument digit 2: NUMERO 2 (KeyDown) +4:1204:0:50:1 //Set instrument digit 2: 2 (KeyDown) +4:1205:0:99:1 //Set instrument digit 3: NUMERO 3 (KeyDown) +4:1205:0:51:1 //Set instrument digit 3: 3 (KeyDown) +4:1206:0:100:1 //Set instrument digit 4: NUMERO 4 (KeyDown) +4:1206:0:52:1 //Set instrument digit 4: 4 (KeyDown) +4:1207:0:101:1 //Set instrument digit 5: NUMERO 5 (KeyDown) +4:1207:0:53:1 //Set instrument digit 5: 5 (KeyDown) +4:1208:0:102:1 //Set instrument digit 6: NUMERO 6 (KeyDown) +4:1208:0:54:1 //Set instrument digit 6: 6 (KeyDown) +4:1209:0:103:1 //Set instrument digit 7: NUMERO 7 (KeyDown) +4:1209:0:55:1 //Set instrument digit 7: 7 (KeyDown) +4:1210:0:104:1 //Set instrument digit 8: NUMERO 8 (KeyDown) +4:1210:0:56:1 //Set instrument digit 8: 8 (KeyDown) +4:1211:0:105:1 //Set instrument digit 9: NUMERO 9 (KeyDown) +4:1211:0:57:1 //Set instrument digit 9: 9 (KeyDown) + +//----( Pattern Context [bottom] - Vol Col (5) )------------ +5:1222:0:48:1 //Set volume digit 0: 0 (KeyDown) +5:1222:0:96:1 //Set volume digit 0: NUMERO 0 (KeyDown) +5:1223:0:49:1 //Set volume digit 1: 1 (KeyDown) +5:1223:0:97:1 //Set volume digit 1: NUMERO 1 (KeyDown) +5:1224:0:50:1 //Set volume digit 2: 2 (KeyDown) +5:1224:0:98:1 //Set volume digit 2: NUMERO 2 (KeyDown) +5:1225:0:51:1 //Set volume digit 3: 3 (KeyDown) +5:1225:0:99:1 //Set volume digit 3: NUMERO 3 (KeyDown) +5:1226:0:52:1 //Set volume digit 4: 4 (KeyDown) +5:1226:0:100:1 //Set volume digit 4: NUMERO 4 (KeyDown) +5:1227:0:53:1 //Set volume digit 5: 5 (KeyDown) +5:1227:0:101:1 //Set volume digit 5: NUMERO 5 (KeyDown) +5:1228:0:54:1 //Set volume digit 6: 6 (KeyDown) +5:1228:0:102:1 //Set volume digit 6: NUMERO 6 (KeyDown) +5:1229:0:55:1 //Set volume digit 7: 7 (KeyDown) +5:1229:0:103:1 //Set volume digit 7: NUMERO 7 (KeyDown) +5:1230:0:56:1 //Set volume digit 8: 8 (KeyDown) +5:1230:0:104:1 //Set volume digit 8: NUMERO 8 (KeyDown) +5:1231:0:57:1 //Set volume digit 9: 9 (KeyDown) +5:1231:0:105:1 //Set volume digit 9: NUMERO 9 (KeyDown) +5:1232:0:86:1 //Vol command - volume: V (KeyDown) +5:1233:0:80:1 //Vol command - pan: P (KeyDown) +5:1234:0:67:1 //Vol command - vol slide up: C (KeyDown) +5:1235:0:68:1 //Vol command - vol slide down: D (KeyDown) +5:1236:0:65:1 //Vol command - vol fine slide up: A (KeyDown) +5:1237:0:66:1 //Vol command - vol fine slide down: B (KeyDown) +5:1238:0:85:1 //Vol command - vibrato speed: U (KeyDown) +5:1239:0:72:1 //Vol command - vibrato: H (KeyDown) +5:1240:0:76:1 //Vol command - XM pan left: L (KeyDown) +5:1241:0:82:1 //Vol command - XM pan right: R (KeyDown) +5:1242:0:71:1 //Vol command - Portamento: G (KeyDown) +5:1243:0:70:1 //Vol command - Portamento Up: F (KeyDown) +5:1244:0:69:1 //Vol command - Portamento Down: E (KeyDown) +5:1246:0:79:1 //Vol command - Offset: O (KeyDown) + +//----( Pattern Context [bottom] - FX Col (6) )------------ +6:1294:0:226:1 //FX midi macro slide: < (KeyDown) +6:1295:1:192:1 //FX combined note delay and note cut: Shift+\xF1 (KeyDown) +6:1295:0:186:1 //FX combined note delay and note cut: AGUDO (KeyDown) +6:1666:0:189:1 //FX parameter extension command: - (KeyDown) + +//----( Pattern Context [bottom] - Param Col (7) )------------ +7:1247:0:48:1 //FX Param digit 0: 0 (KeyDown) +7:1247:0:96:1 //FX Param digit 0: NUMERO 0 (KeyDown) +7:1248:0:49:1 //FX Param digit 1: 1 (KeyDown) +7:1248:0:97:1 //FX Param digit 1: NUMERO 1 (KeyDown) +7:1249:0:50:1 //FX Param digit 2: 2 (KeyDown) +7:1249:0:98:1 //FX Param digit 2: NUMERO 2 (KeyDown) +7:1250:0:51:1 //FX Param digit 3: 3 (KeyDown) +7:1250:0:99:1 //FX Param digit 3: NUMERO 3 (KeyDown) +7:1251:0:52:1 //FX Param digit 4: 4 (KeyDown) +7:1251:0:100:1 //FX Param digit 4: NUMERO 4 (KeyDown) +7:1252:0:53:1 //FX Param digit 5: 5 (KeyDown) +7:1252:0:101:1 //FX Param digit 5: NUMERO 5 (KeyDown) +7:1253:0:54:1 //FX Param digit 6: 6 (KeyDown) +7:1253:0:102:1 //FX Param digit 6: NUMERO 6 (KeyDown) +7:1254:0:55:1 //FX Param digit 7: 7 (KeyDown) +7:1254:0:103:1 //FX Param digit 7: NUMERO 7 (KeyDown) +7:1255:0:56:1 //FX Param digit 8: 8 (KeyDown) +7:1255:0:104:1 //FX Param digit 8: NUMERO 8 (KeyDown) +7:1256:0:57:1 //FX Param digit 9: 9 (KeyDown) +7:1256:0:105:1 //FX Param digit 9: NUMERO 9 (KeyDown) +7:1257:0:65:1 //FX Param digit A: A (KeyDown) +7:1258:0:66:1 //FX Param digit B: B (KeyDown) +7:1259:0:67:1 //FX Param digit C: C (KeyDown) +7:1260:0:68:1 //FX Param digit D: D (KeyDown) +7:1261:0:69:1 //FX Param digit E: E (KeyDown) +7:1262:0:70:1 //FX Param digit F: F (KeyDown) + +//----( Sample Context [bottom] (8) )------------ +8:1380:2:84:1 //Trim sample around loop points: Ctrl+T (KeyDown) +8:1383:0:8:1 //Silence sample selection: RETROCESO (KeyDown) +8:1384:1:78:1 //Normalise Sample: Shift+N (KeyDown) +8:1385:3:65:1 //Amplify Sample: Shift+Ctrl+A (KeyDown) +8:1385:2:77:1 //Amplify Sample: Ctrl+M (KeyDown) +8:1381:3:82:1 //Reverse sample: Shift+Ctrl+R (KeyDown) +8:1382:0:46:1 //Delete sample selection: SUPR (KeyDown) +8:1386:0:107:1 //Zoom Out: TECLA DE ADICION (KeyDown) +8:1387:0:109:1 //Zoom In: TECLA DE SUSTRACCION (KeyDown) +8:1784:2:73:1 //Invert sample phase: Ctrl+I (KeyDown) +8:1785:2:85:1 //Signed/Unsigned conversion: Ctrl+U (KeyDown) +8:1790:2:69:1 //Remove DC Offset: Ctrl+E (KeyDown) +8:1856:2:68:1 //Quick fade: Ctrl+D (KeyDown) +8:1857:2:76:1 //Crossfade sample loop: Ctrl+L (KeyDown) + +//----( Instrument Context [bottom] (9) )------------ +9:1837:0:107:5 //Zoom In: TECLA DE ADICION (KeyDown|KeyHold) +9:1838:0:109:5 //Zoom Out: TECLA DE SUSTRACCION (KeyDown|KeyHold) +9:1825:1:9:5 //Select previous envelope point: Shift+TABULACION (KeyDown|KeyHold) +9:1826:0:9:5 //Select next envelope point: TABULACION (KeyDown|KeyHold) +9:1821:0:37:5 //Move envelope point left: FLECHA IZQUIERDA (KeyDown|KeyHold) +9:1822:0:39:5 //Move envelope point right: FLECHA DERECHA (KeyDown|KeyHold) +9:1823:0:38:5 //Move envelope point up: FLECHA ARRIBA (KeyDown|KeyHold) +9:1834:0:33:5 //Move envelope point up (big step): RE PAG (KeyDown|KeyHold) +9:1824:0:40:5 //Move envelope point down: FLECHA ABAJO (KeyDown|KeyHold) +9:1835:0:34:5 //Move envelope point down (big step): AV PAG (KeyDown|KeyHold) +9:1827:0:45:1 //Insert envelope point: INSERT (KeyDown) +9:1828:0:46:1 //Remove envelope point: SUPR (KeyDown) +9:1828:0:8:1 //Remove envelope point: RETROCESO (KeyDown) +9:1829:0:36:1 //Set loop start: INICIO (KeyDown) +9:1830:0:35:1 //Set loop end: FIN (KeyDown) +9:1831:2:36:1 //Set sustain loop start: Ctrl+INICIO (KeyDown) +9:1832:2:35:1 //Set sustain loop end: Ctrl+FIN (KeyDown) +9:1833:2:82:1 //Toggle release node: Ctrl+R (KeyDown) + +//----( Comments Context [bottom] (10) )------------ + +//----( Unknown Context (11) )------------ + +//----( Unknown Context (12) )------------ + +//----( Plugin GUI Context (13) )------------ +13:1763:0:109:5 //Previous plugin preset: TECLA DE SUSTRACCION (KeyDown|KeyHold) +13:1764:0:107:5 //Next plugin preset: TECLA DE ADICION (KeyDown|KeyHold) +13:1782:2:109:5 //Plugin preset backward jump: Ctrl+TECLA DE SUSTRACCION (KeyDown|KeyHold) +13:1783:2:107:5 //Plugin preset forward jump: Ctrl+TECLA DE ADICION (KeyDown|KeyHold) +13:1765:3:68:1 //Randomize plugin parameters: Shift+Ctrl+D (KeyDown) +13:1839:2:82:1 //Toggle parameter recording: Ctrl+R (KeyDown) +13:1840:2:75:1 //Pass key presses to plugin: Ctrl+K (KeyDown) +13:1841:2:66:1 //Bypass plugin: Ctrl+B (KeyDown) + +//----( General Context [top] (14) )------------ + +//----( Pattern Context [top] (15) )------------ + +//----( 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) )------------ + +//----( Orderlist (19) )------------ +19:1802:0:46:5 //Delete Order: SUPR (KeyDown|KeyHold) +19:1803:0:45:5 //Insert Order: INSERT (KeyDown|KeyHold) +19:1804:0:13:5 //Edit Pattern: ENTRAR (KeyDown|KeyHold) +19:1805:0:9:5 //Switch to pattern editor: TABULACION (KeyDown|KeyHold) +19:1794:0:37:5 //Previous Order: FLECHA IZQUIERDA (KeyDown|KeyHold) +19:1794:0:38:5 //Previous Order: FLECHA ARRIBA (KeyDown|KeyHold) +19:1795:0:39:5 //Next Order: FLECHA DERECHA (KeyDown|KeyHold) +19:1795:0:40:5 //Next Order: FLECHA ABAJO (KeyDown|KeyHold) +19:1796:0:36:5 //First Order: INICIO (KeyDown|KeyHold) +19:1797:0:35:5 //Last Order: FIN (KeyDown|KeyHold) +19:1807:0:48:5 //Pattern index digit 0: 0 (KeyDown|KeyHold) +19:1807:0:96:5 //Pattern index digit 0: NUMERO 0 (KeyDown|KeyHold) +19:1808:0:49:5 //Pattern index digit 1: 1 (KeyDown|KeyHold) +19:1808:0:97:5 //Pattern index digit 1: NUMERO 1 (KeyDown|KeyHold) +19:1809:0:50:5 //Pattern index digit 2: 2 (KeyDown|KeyHold) +19:1809:0:98:5 //Pattern index digit 2: NUMERO 2 (KeyDown|KeyHold) +19:1810:0:51:5 //Pattern index digit 3: 3 (KeyDown|KeyHold) +19:1810:0:99:5 //Pattern index digit 3: NUMERO 3 (KeyDown|KeyHold) +19:1811:0:52:5 //Pattern index digit 4: 4 (KeyDown|KeyHold) +19:1811:0:100:5 //Pattern index digit 4: NUMERO 4 (KeyDown|KeyHold) +19:1812:0:53:5 //Pattern index digit 5: 5 (KeyDown|KeyHold) +19:1812:0:101:5 //Pattern index digit 5: NUMERO 5 (KeyDown|KeyHold) +19:1813:0:54:5 //Pattern index digit 6: 6 (KeyDown|KeyHold) +19:1813:0:102:5 //Pattern index digit 6: NUMERO 6 (KeyDown|KeyHold) +19:1814:0:55:5 //Pattern index digit 7: 7 (KeyDown|KeyHold) +19:1814:0:103:5 //Pattern index digit 7: NUMERO 7 (KeyDown|KeyHold) +19:1815:0:56:5 //Pattern index digit 8: 8 (KeyDown|KeyHold) +19:1815:0:104:5 //Pattern index digit 8: NUMERO 8 (KeyDown|KeyHold) +19:1816:0:57:5 //Pattern index digit 9: 9 (KeyDown|KeyHold) +19:1816:0:105:5 //Pattern index digit 9: NUMERO 9 (KeyDown|KeyHold) +19:1817:0:107:5 //Increas... [truncated message content] |
From: <sag...@us...> - 2011-04-01 15:15:48
|
Revision: 836 http://modplug.svn.sourceforge.net/modplug/?rev=836&view=rev Author: saga-games Date: 2011-04-01 15:15:40 +0000 (Fri, 01 Apr 2011) Log Message: ----------- [Fix] Pattern Editor: Editing patterns through the Note Properties created just one undo point per module (http://bugs.openmpt.org/view.php?id=56#c118) (tx Harbinger) [Fix] Pattern Editor: Setting the PC note plugin from the Note Properties didn't work. [New] Instrument Editor: Clicking on an empty plugin slot in the plugin dropdown list opens the "Add Plugin" dialog (tx coda) [New] Plugin Editor: New menu entry: Create instrument from plugin [Mod] Options: "No extra-loud samples" is now enabled by default (more suitable for Mixmodes RC3 and Original) [Mod] OpenMPT: Version is now 1.19.01.00 Final Modified Paths: -------------- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp trunk/OpenMPT/mptrack/AbstractVstEditor.h trunk/OpenMPT/mptrack/Ctrl_ins.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp trunk/OpenMPT/mptrack/resource.h trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/packageTemplate/History.txt Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.cpp =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-04-01 15:15:40 UTC (rev 836) @@ -46,6 +46,7 @@ ON_COMMAND(ID_NEXTVSTPRESET, OnSetNextVSTPreset) ON_COMMAND(ID_VSTPRESETBACKWARDJUMP,OnVSTPresetBackwardJump) ON_COMMAND(ID_VSTPRESETFORWARDJUMP, OnVSTPresetForwardJump) + ON_COMMAND(ID_PLUGINTOINSTRUMENT, OnCreateInstrument) ON_COMMAND_RANGE(ID_PRESET_SET, ID_PRESET_SET+MAX_PLUGPRESETS, OnSetPreset) ON_MESSAGE(WM_MOD_KEYCOMMAND, OnCustomKeyMsg) //rewbs.customKeys ON_COMMAND_RANGE(ID_PLUGSELECT, ID_PLUGSELECT+MAX_MIXPLUGINS, OnToggleEditor) //rewbs.patPlugName @@ -188,7 +189,11 @@ char rawname[256]; if(!m_pVstPlugin->GetProgramNameIndexed(index, -1, rawname)) { - strcpy(rawname, ""); + // Fallback: Try to get current program name. + if(m_pVstPlugin->Dispatch(effGetProgramName, 0, 0, rawname, 0) != 1) + { + strcpy(rawname, ""); + } } SetNullTerminator(rawname); CreateVerifiedProgramName(rawname, sizeof(rawname), name, sizeof(name), index); @@ -202,9 +207,9 @@ void CAbstractVstEditor::OnSetPreset(UINT nID) -//--------------------------------------------- +//-------------------------------------------- { - int nIndex=nID-ID_PRESET_SET; + int nIndex = nID - ID_PRESET_SET; if (nIndex>=0) { m_pVstPlugin->SetCurrentProgram(nIndex); @@ -310,7 +315,7 @@ } LRESULT CAbstractVstEditor::OnCustomKeyMsg(WPARAM wParam, LPARAM /*lParam*/) -//---------------------------------------------------------------------- +//-------------------------------------------------------------------------- { if (wParam == kcNull) return NULL; @@ -365,8 +370,7 @@ if(m_nInstrument < 0 && m_pVstPlugin->CanRecieveMidiEvents()) { CModDoc *pModDoc = m_pVstPlugin->GetModDoc(); - CSoundFile *pSndFile = m_pVstPlugin->GetSoundFile(); - if(!pModDoc || !pSndFile) + if(pModDoc == nullptr) return false; if(!m_pVstPlugin->isInstrument() || pModDoc->GetSoundFile()->GetModSpecifications().instrumentsMax == 0 || @@ -375,28 +379,7 @@ return false; } else { - // try to set up a new instrument - bool bFirst = (pSndFile->GetNumInstruments() == 0); - INSTRUMENTINDEX nIns = pModDoc->InsertInstrument(0); - if(nIns == INSTRUMENTINDEX_INVALID) - return false; - - MODINSTRUMENT *pIns = pSndFile->Instruments[nIns]; - m_nInstrument = nIns; - - _snprintf(pIns->name, CountOf(pIns->name) - 1, _T("%d: %s"), m_pVstPlugin->GetSlot() + 1, pSndFile->m_MixPlugins[m_pVstPlugin->GetSlot()].Info.szName); - strncpy(pIns->filename, pSndFile->m_MixPlugins[m_pVstPlugin->GetSlot()].Info.szLibraryName, CountOf(pIns->filename) - 1); - pIns->nMixPlug = (PLUGINDEX)m_pVstPlugin->GetSlot() + 1; - pIns->nMidiChannel = 1; - // People will forget to change this anyway, so the following lines can lead to some bad surprises after re-opening the module. - //pIns->wMidiBank = (WORD)((m_pVstPlugin->GetCurrentProgram() >> 7) + 1); - //pIns->nMidiProgram = (BYTE)((m_pVstPlugin->GetCurrentProgram() & 0x7F) + 1); - - pModDoc->UpdateAllViews(NULL, (nIns << HINT_SHIFT_INS) | HINT_INSTRUMENT | HINT_INSNAMES | HINT_ENVELOPE | (bFirst ? HINT_MODTYPE : 0)); - if(pSndFile->GetModSpecifications().supportsPlugins) - pModDoc->SetModified(); - - return true; + return CreateInstrument(); } } else { @@ -741,11 +724,58 @@ } void CAbstractVstEditor::OnVSTPresetForwardJump() -//---------------------------------------------------- +//----------------------------------------------- { OnSetPreset(min(10+ID_PRESET_SET+m_pVstPlugin->GetCurrentProgram(), ID_PRESET_SET+m_pVstPlugin->GetNumPrograms()-1)); } + +void CAbstractVstEditor::OnCreateInstrument() +//------------------------------------------- +{ + CreateInstrument(); +} + + +// Try to set up a new instrument that is linked to the current plugin. +bool CAbstractVstEditor::CreateInstrument() +//----------------------------------------- +{ + CModDoc *pModDoc = m_pVstPlugin->GetModDoc(); + CSoundFile *pSndFile = m_pVstPlugin->GetSoundFile(); + if(pModDoc == nullptr || pSndFile == nullptr) + { + return false; + } + + bool bFirst = (pSndFile->GetNumInstruments() == 0); + INSTRUMENTINDEX nIns = pModDoc->InsertInstrument(0); + if(nIns == INSTRUMENTINDEX_INVALID) + { + return false; + } + + MODINSTRUMENT *pIns = pSndFile->Instruments[nIns]; + m_nInstrument = nIns; + + _snprintf(pIns->name, CountOf(pIns->name) - 1, _T("%d: %s"), m_pVstPlugin->GetSlot() + 1, pSndFile->m_MixPlugins[m_pVstPlugin->GetSlot()].Info.szName); + strncpy(pIns->filename, pSndFile->m_MixPlugins[m_pVstPlugin->GetSlot()].Info.szLibraryName, CountOf(pIns->filename) - 1); + pIns->nMixPlug = (PLUGINDEX)m_pVstPlugin->GetSlot() + 1; + pIns->nMidiChannel = 1; + // People will forget to change this anyway, so the following lines can lead to some bad surprises after re-opening the module. + //pIns->wMidiBank = (WORD)((m_pVstPlugin->GetCurrentProgram() >> 7) + 1); + //pIns->nMidiProgram = (BYTE)((m_pVstPlugin->GetCurrentProgram() & 0x7F) + 1); + + pModDoc->UpdateAllViews(NULL, (nIns << HINT_SHIFT_INS) | HINT_INSTRUMENT | HINT_INSNAMES | HINT_ENVELOPE | (bFirst ? HINT_MODTYPE : 0)); + if(pSndFile->GetModSpecifications().supportsPlugins) + { + pModDoc->SetModified(); + } + + return true; +} + + void CAbstractVstEditor::PrepareToLearnMacro(UINT nID) { m_nLearnMacro = (nID-ID_LEARN_MACRO_FROM_PLUGGUI); Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.h =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.h 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.h 2011-04-01 15:15:40 UTC (rev 836) @@ -23,6 +23,7 @@ int GetLearnMacro(); void UpdatePresetField(); + bool CreateInstrument(); afx_msg void OnLoadPreset(); afx_msg void OnSavePreset(); @@ -37,6 +38,7 @@ afx_msg void OnSetNextVSTPreset(); afx_msg void OnVSTPresetBackwardJump(); afx_msg void OnVSTPresetForwardJump(); + afx_msg void OnCreateInstrument(); afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM); //rewbs.customKeys //Overridden methods: Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp 2011-04-01 15:15:40 UTC (rev 836) @@ -9,6 +9,7 @@ #include "dlg_misc.h" #include "tuningDialog.h" #include "misc_util.h" +#include "Vstplug.h" #pragma warning(disable:4244) //conversion from 'type1' to 'type2', possible loss of data @@ -2088,7 +2089,23 @@ if (pIns->nMixPlug) //if we have not just set to no plugin { - PSNDMIXPLUGIN pPlug = &(m_pSndFile->m_MixPlugins[pIns->nMixPlug-1]); + PSNDMIXPLUGIN pPlug = &(m_pSndFile->m_MixPlugins[pIns->nMixPlug - 1]); + if (pPlug == nullptr || pPlug->pMixPlugin == nullptr) + { + // No plugin in this slot: Ask user to add one. + CSelectPluginDlg dlg(m_pModDoc, nPlug - 1, this); + if (dlg.DoModal() == IDOK) + { + if(m_pSndFile->GetModSpecifications().supportsPlugins) + { + m_pModDoc->SetModified(); + } + UpdatePluginList(); + m_pModDoc->UpdateAllViews(NULL, HINT_MIXPLUGINS, NULL); + } + + } + if (pPlug && pPlug->pMixPlugin) { ::EnableWindow(::GetDlgItem(m_hWnd, IDC_INSVIEWPLG), true); @@ -2102,7 +2119,6 @@ } return; } - } } Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-01 15:15:40 UTC (rev 836) @@ -194,7 +194,7 @@ // Pattern Setup DWORD CMainFrame::m_dwPatternSetup = PATTERN_PLAYNEWNOTE | PATTERN_EFFECTHILIGHT | PATTERN_SMALLFONT | PATTERN_CENTERROW - | PATTERN_DRAGNDROPEDIT | PATTERN_FLATBUTTONS + | PATTERN_DRAGNDROPEDIT | PATTERN_FLATBUTTONS | PATTERN_NOEXTRALOUD | PATTERN_2NDHIGHLIGHT | PATTERN_STDHIGHLIGHT /*| PATTERN_HILITETIMESIGS*/ | PATTERN_SHOWPREVIOUS | PATTERN_CONTSCROLL | PATTERN_SYNCMUTE | PATTERN_AUTODELAY | PATTERN_NOTEFADE; DWORD CMainFrame::m_nRowSpacing = 16; // primary highlight (measures) @@ -823,7 +823,7 @@ if (!m_wndToolBar.Create(this)) return -1; if (!m_wndStatusBar.Create(this)) return -1; if (!m_wndTree.Create(this, IDD_TREEVIEW, CBRS_LEFT|CBRS_BORDER_RIGHT, IDD_TREEVIEW)) return -1; - m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)); + m_wndStatusBar.SetIndicators(indicators, CountOf(indicators)); m_wndToolBar.Init(this); m_wndTree.RecalcLayout(); @@ -3078,7 +3078,7 @@ str += (librarynames) ? p->GetLibraryName() : p->GetName(); if(str.GetLength() <= size0) str += "undefined"; - CBox.AddString(str); + CBox.SetItemData(CBox.AddString(str), iPlug + 1); } #endif // NO_VST } @@ -3094,8 +3094,8 @@ //----------------------------------------------------------------------- { char s[72], sname[64]; - UINT nParams = plug.GetNumParameters(); - for (UINT i=0; i<nParams; i++) + const PlugParamIndex nParams = plug.GetNumParameters(); + for (PlugParamIndex i = 0; i < nParams; i++) { plug.GetParamName(i, sname, sizeof(sname)); wsprintf(s, "%02d: %s", i, sname); Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2011-04-01 15:15:40 UTC (rev 836) @@ -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 instruments.")) +#define str_preampChangeNote GetStrI18N(_TEXT("Note: The Pre-Amp setting affects sample volume only. Changing it may cause undesired effects on volume balance between sample based instruments and plugin instruments.\nIn other words: Don't touch this slider unless you know what you are doing.")) //#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" Modified: trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp =================================================================== --- trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2011-04-01 15:15:40 UTC (rev 836) @@ -621,6 +621,7 @@ m_nRow = nRow; m_nChannel = nChannel; m_nPattern = nPat; + m_bModified = false; // Init Pages if (m_pageNote) m_pageNote->Init(m_Command); if (m_pageVolume) m_pageVolume->Init(m_Command); @@ -871,7 +872,7 @@ CSoundFile* pSndFile = m_pModDoc->GetSoundFile(); m_nInstr = combo->GetItemData(n); //Checking whether note names should be recreated. - if(pSndFile && pSndFile->Instruments[m_nInstr] && pSndFile->Instruments[oldInstr]) + if(!MODCOMMAND::IsPcNote(m_nNote) && pSndFile && pSndFile->Instruments[m_nInstr] && pSndFile->Instruments[oldInstr]) { if(pSndFile->Instruments[m_nInstr]->pTuning != pSndFile->Instruments[oldInstr]->pTuning) UpdateDialog(); Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/resource.h 2011-04-01 15:15:40 UTC (rev 836) @@ -1185,6 +1185,7 @@ #define ID_SAMPLE_QUICKFADE 60454 #define ID_EDIT_MIXPASTE_ITSTYLE 60455 #define ID_VIEW_MPTHACKS 60456 +#define ID_PLUGINTOINSTRUMENT 60457 // Next default values for new objects // @@ -1192,7 +1193,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 529 -#define _APS_NEXT_COMMAND_VALUE 60457 +#define _APS_NEXT_COMMAND_VALUE 60458 #define _APS_NEXT_CONTROL_VALUE 2435 #define _APS_NEXT_SYMED_VALUE 901 #endif Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/mptrack/version.h 2011-04-01 15:15:40 UTC (rev 836) @@ -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 19 -#define VER_MINOR 00 -#define VER_MINORMINOR 31 +#define VER_MINOR 01 +#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 2011-04-01 15:03:17 UTC (rev 835) +++ trunk/OpenMPT/packageTemplate/History.txt 2011-04-01 15:15:40 UTC (rev 836) @@ -7,18 +7,16 @@ [Reg]: known issue / regression [Mod]: change [Var]: other -(tx XYZ): thanks to XYZ for telling us about the bug +(tx XYZ): thanks to XYZ for telling us about the bug / requesting the feature -v1.19.01.00 (March 2011, revision 833) +v1.19.01.00 (April 2011, revision 836) -------------------------------------- Pattern tab - [New] <Jojo> Clicking and dragging the row numbers selects the whole row now (Excel / Calc style) - see http://bugs.openmpt.org/view.php?id=45 + [New] <Jojo> Clicking and dragging the row numbers selects the whole row in Excel / Calc style (http://bugs.openmpt.org/view.php?id=45) [New] <Jojo> The new keyboard shortcuts "Select beat" and "Select measure" can be used to automatically extend the current selection to the beat / measure boundaries. [New] <Jojo> Experimental feature: Play the whole pattern row when entering notes and chords into the pattern editor. This can be enabled from the setup screen. - [Imp] <Jojo> Special paste modes have been moved to a sub menu in the context menu, to save some space. - [Imp] <Jojo> Status bar now indicates if highpass filter is enabled on a channel. (http://bugs.openmpt.org/view.php?id=92) - [Mod] <Jojo> Using the Goto Dialog should now update channel parameters and set the elapsed time. (http://bugs.openmpt.org/view.php?id=28) + [Mod] <Jojo> Using the Goto Dialog updates channel parameters and sets the elapsed time now. (http://bugs.openmpt.org/view.php?id=28) [Mod] <Jojo> Undo steps have been increased from 100 to 1000. [Fix] <Jojo> Shrink selection is more consistent with Shrink pattern now: Entries on odd rows are not ignored anymore if there is no entry in the even rows. Also, cleaning of the pattern after shrinking the selection has been fixed - it cleaned whole commands instead of just the selected parts of a command. (http://bugs.openmpt.org/view.php?id=89) [Fix] <Jojo> Cursor paste was possible even when editing was disabled. @@ -37,6 +35,7 @@ Pattern tab::Note properties [Fix] <Jojo> The meaning of Q0x was displayed wrong for S3M / IT. [Fix] <Jojo> Changing a value didn't create an undo point. (http://bugs.openmpt.org/view.php?id=56) + [Fix] <Jojo> Setting the PC note plugin didn't work. Pattern tab::Find/replace [New] <Jojo> Added Find / Replace mode: Find in current pattern selection. (http://bugs.openmpt.org/view.php?id=42) @@ -44,6 +43,8 @@ [Mod] <Jojo> "Replace All" just creates one undo point now. Pattern tab::GUI + [Imp] <Jojo> Special paste modes have been moved to a sub menu in the context menu, to save some space. + [Imp] <Jojo> Status bar now indicates if highpass filter is enabled on a channel. (http://bugs.openmpt.org/view.php?id=92) [Imp] <Jojo> The dodgy note colour is now also customisable. [Mod] <Jojo> When removing a channel (via context menu) that contains no data in any pattern, no warning is shown anymore. @@ -59,6 +60,7 @@ [Fix] <re> Changing zoom level should now preserve the view position better. (http://bugs.openmpt.org/view.php?id=3) Instrument tab + [New] <Jojo> Clicking on an empty plugin slot in the plugin dropdown list opens the "Add Plugin" dialog (tx coda) [Imp] <re> Ctrl + Mouse Wheel can now be used for zooming into the envelopes. [Imp] <Jojo> When pressing the up arrow key in the sample map while the cursor is on the lowest note (C-0), the sample map doesn't lose focus anymore. It is also not possible anymore to move the sample map out of view by clicking the area above the lowest note. [Mod] <Jojo> Copying and pasting envelopes with no points isn't possible anymore. (Who wants to do that anyway?) @@ -69,6 +71,7 @@ VST [New] <Jojo> Plugins can now request common file dialogs (file and directory selection). + [New] <Jojo> New menu entry in the plugin editor: Create instrument from plugin [Mod] <Jojo> When automatically inserting a new instrument from the VST editor, the bank and patch values are now not filled in anymore, so it is easier to change to another patch while editing. [Mod] <Jojo> Various small improvements to support VST 2.4 plugins better. [Fix] <Jojo> Speaker arrangement is now sent to the plugins upon initialization. This fixes Voxengo SPAN 2 (a VST 2.4 plugin). Does this break other multichannel plugins? @@ -95,26 +98,28 @@ IT [New] <Jojo> Edit history information can now be read from and saved to IT / MPTM files. This is based on an undocumented feature in Impulse Tracker. Use View -> Edit History for viewing or deleting this information. [Imp] <Jojo> IT files made with Modplug Tracker 1.00a5 are now also detected as such. Since long patterns can also be created in other trackers (e.g. Chibi), long patterns are not used to identify files made with MPT anymore. - [Imp] <Jojo> IT Loader: Autovibrato sweep is now fixed when loading IT files made with old versions of (Open)MPT. [Mod] <Jojo> Sane values are used again for the "cwtv" and "cmwt" header fields when saving IT files; in fact the same values as in compatibility export are used. To be able to distinguish between raped and compatibility-exported IT files, "OMPT" is written in the "reserved" header field. As a consequence, IT files made with OpenMPT can now be loaded in Impulse Tracker again. - [Mod] <Jojo> IT Loader: MIDI macros are now cleared when loading IT files made with old Impulse Tracker versions (< 2.14), so that Zxx commands won't break the songs anymore (fixes denonde.it, fix from Schism Tracker). [Fix] <Jojo> Incorrect notes were memorized for PPS (and possibly other effects) when working with instruments that had non-default note assignments (f.e. C-5 => D-4) [Fix] <Jojo> In compatible mode, bidi loops are now treated like in IT's software mixer. (http://bugs.openmpt.org/view.php?id=29) [Fix] <Jojo> Sample autovibrato is now hopefully a bit closer to Impulse Tracker in compatible mode... (http://bugs.openmpt.org/view.php?id=5) [Fix] <Jojo> The envelope handling was altered slightly to work more like in Schism Tracker. This fixes a combination of Envelope Carry + Portamento as it can be found in "electric bunny" by Alpha C. [Fix] <Jojo> Various fixes to playback of multi-sample instruments. "Ultima Ratio" by Nebularia and "Shuttle Departure" by Sphenx sound better now. [Fix] <Jojo> The extended sample map is not saved anymore in the instrument headers when using compatibility export. - [Fix] <Jojo> IT Loader / Saver: Note mapping items that aren't notes are now ignored. - [Fix] <Jojo> IT Saver: Non-existing envelopes are now replaced by a default (disabled) envelope, so that they can still be edited in Impulse Tracker. +IT::Loading and Saving + [Imp] <Jojo> Autovibrato sweep is now fixed when loading IT files made with old versions of (Open)MPT. + [Mod] <Jojo> MIDI macros are now cleared when loading IT files made with old Impulse Tracker versions (< 2.14), so that Zxx commands won't break the songs anymore (fixes denonde.it, fix from Schism Tracker). + [Fix] <Jojo> Note mapping items that aren't notes (f.e. empty notes) are now ignored when loading and saving. + [Fix] <Jojo> When saving, non-existing envelopes are now replaced by a default (disabled) envelope, so that they can still be edited in Impulse Tracker. + MPTM - [New] <Jojo> Each pattern can now have a custom time signature (rows per beat and rows per measure) which can be set from the pattern properties dialog. + [New] <Jojo> Each pattern can now have a custom time signature (rows per beat and rows per measure) which can be set from the pattern properties dialog. (http://forum.openmpt.org/index.php?topic=4022.0) [New] <Jojo> Edit history information (read the "IT" section above for an explanation) XM - [Fix] <Jojo> XM Compatibility: Various mind-boggling combinations of EDx, notes and instrument numbers should work correctly now. - [Fix] <Jojo> XM Compatibility: When there's a instrument number next to a 3xx effect which differs from the previous instrument number, it resets the instrument properties of the previous instrument now. - [Fix] <Jojo> XM Compatibility: Portamento combined with an Offset command results in the offset command being ignored. + [Fix] <Jojo> Various mind-boggling combinations of EDx, notes and instrument numbers should work correctly in compatible mode now. + [Fix] <Jojo> When there's a instrument number next to a 3xx effect which differs from the previous instrument number, it resets the instrument properties of the previous instrument in compatible mode. + [Fix] <Jojo> Portamento combined with an Offset command results in the offset command being ignored in compatible mode. [Fix] <Jojo> XM Loader: Fixed handling of instruments with no samples, so that instruments assigned to VST plugins work correctly. MOD @@ -122,9 +127,9 @@ [Fix] <Jojo> The maximum speed for MOD files was off by one in some places (31 instead of 32). MOD::Loading - [New] <Jojo> Added a heuristic detection for VBlank MODs. Most MODs use the CIA timer instead of VBlank timing, but some don't. - [New] <Jojo> Added a heuristic detection for PT 1.x playback mode: If there is pattern data that looks like it needs on-the-fly sample swapping, PT 1.x mode is enabled. - [New] <Jojo> Added a heuristic detection for MODs with 7-bit panning, which is then automatically converted to 8-bit panning. + [New] <Jojo> Heuristic detection for VBlank MODs. Most MODs use the CIA timer instead of VBlank timing, but some don't. + [New] <Jojo> Heuristic detection for PT 1.x playback mode: If there is pattern data that looks like it needs on-the-fly sample swapping, PT 1.x mode is enabled. + [New] <Jojo> Heuristic detection for MODs with 7-bit panning, which is then automatically converted to 8-bit panning. [Fix] <Jojo> Tentative fix for MODs with short loops at the sample start that were most likely not intended. S3M @@ -133,8 +138,8 @@ [Fix] <Jojo> S3M Loader: Fix to pattern loader (for empty patterns) [Fix] <Jojo> Removed the X param (#) effect from the supported effect list. [Fix] <Jojo> Speed and tempo values are now adjusted to what Scream Tracker actually expects (speed 1 - 254, tempo 33 - 255) - anything out of this range is ignored by Scream Tracker, so it is now also ignored by OpenMPT. - [Fix] <Jojo> Pattern breaks >= C40 are now ingnored. - [Fix] <Jojo> Global volume commands > V40 are now ignored. Global volume is processed on tick 1 to emulate ST3's behaviour (far from perfect). + [Fix] <Jojo> Pattern breaks >= C40 are now ignored. + [Fix] <Jojo> Global volume commands > V40 are now ignored. Other modules [Imp] <Jojo> Garbage characters in sample / instrument / song names should be gone now.. This should f.e. avoid sample names like " ntitled" turning up in modules after deleting sample names. @@ -160,6 +165,7 @@ [Mod] <Jojo> The "Original" mix mode now also has a version number (1.16) to reflect what the "original" thing is. [Mod] <Jojo> Updated genre list in the MP3 export dialog. [Mod] <Jojo> When using the ACM MP3 codec, 320kbit/s bitrate should now be available. + [Mod] <Jojo> "No extra-loud samples" is now enabled by default (as it's more suitable for mixmodes RC3 and Original) [Mod] <Jojo> The MMX acceleration label in the Soundcard setup dialog is now updated according to the multimedia extensions that are supported by the CPU (3DNow! / SSE) [Mod] <Jojo> Updated unmo3.dll to version 2.4.0.1 [Mod] <Jojo> Updated the internet link list in the Help menu. @@ -766,16 +772,14 @@ Mod conversion [Imp] <Jojo> Convert E9x to Q8x as Q0x actually means "continue" and not "no change" for the volume change. - [Imp] <Jojo> Even better conversion of various pattern effects, including 8-Bit Panning, Arpeggio (XM swaps the two parameters) including Surround, Note Cut/Off/Fade conversion, MOD retrigger, XM->IT volume column limitations, illegal notes). + [Imp] <Jojo> Even better conversion of various pattern effects, including 7/8-Bit Panning, Surround, Note Cut/Off/Fade conversion, MOD retrigger, XM->IT volume column limitations, illegal notes). [Imp] <Jojo> Proper conversion of Pxy effect. [Imp] <Jojo> Full volume column conversion, resetting default global volume / tempo / speed for MOD files. [Imp] <Jojo> \xx is converted to Zxx when converting to / saving S3M files or "compatible" IT files. [Imp] <Jojo> Somewhat decent conversion of Kxx (Key Off) from XM to S3M/IT. [Imp] <Jojo> Trim instrument envelopes if they're too long for the new format. - [Imp] <Jojo> Convert 500/600 commands properly from MOD to any format, Adjust sustain loops for XM files, removed XM arpeggio conversion (it might be unwanted). + [Imp] <Jojo> Convert 500/600 commands properly from MOD to any format, Adjust sustain loops for XM files. [Imp] <Jojo> Try to use fix commands that don't have a "memory" (00 value) in XM (Arpeggio) and MOD format (Arpeggio and a few others) by using the previous value. - [Fix] <Jojo> Proper conversion between IT 8-Bit panning effect and S3M 7-Bit panning effect with surround. - [Fix] <Jojo> Unset release nodes were corrupted when converting modules. Playback (see also format-specific changes below) [Imp] <Jojo> Mixing: It's now possible to go down to 1ms latency (works with ASIO). @@ -843,7 +847,7 @@ S3M::Loading [Imp] <Jojo> Smarter Zxx conversion without message box (heuristic detection). - [Fix] <Jojo> Limit minimum sample preamp value to 16. + [Fix] <Jojo> Minimum sample preamp value is now 16 (like in ST3). [Fix] <Jojo> Small modifications to pattern loader to load somewhat broken S3M files (fix from xmp). [Fix] <Jojo> Don't reset global volume to max if it is 0 for "new" S3M modules. [Fix] <Jojo> Disable loop for sample with very short loop at the beginning. @@ -901,7 +905,7 @@ [Fix] <Jojo> F20 won't turn into G20. MOD::Playback compatibility - [Fix] <Jojo> 8-Bit Panning is not 7-Bit panning (using 800...8FF instead of 800...880 now - fixes f.e. DOPE.MOD). + [Fix] <Jojo> Using 8-Bit (800-8FF) Panning instead of 7-Bit panning (800-880) now - fixes f.e. DOPE.MOD. [Fix] <Jojo> Pattern loops are now handled correctly. Setup This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-03 21:35:12
|
Revision: 840 http://modplug.svn.sourceforge.net/modplug/?rev=840&view=rev Author: saga-games Date: 2011-04-03 21:35:05 +0000 (Sun, 03 Apr 2011) Log Message: ----------- [New] The update checker is back, this time not using WinHTTP but WinINet and with much cleaner code and a proper configuration page. [New] ... Actually I forgot to commit mptrack.rc in revision 836, so there is no "Create instrument from plugin" command in OpenMPT 1.19.01.00. :-( Consider this to be my april fool's joke, even if it wasn't meant to be. :-P Revision Links: -------------- http://modplug.svn.sourceforge.net/modplug/?rev=836&view=rev Modified Paths: -------------- trunk/OpenMPT/installer/install.iss trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/Moptions.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/Mptrack.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/mptrack.vcproj trunk/OpenMPT/mptrack/mptrack_08.vcproj trunk/OpenMPT/mptrack/resource.h Added Paths: ----------- trunk/OpenMPT/mptrack/UpdateCheck.cpp trunk/OpenMPT/mptrack/UpdateCheck.h Modified: trunk/OpenMPT/installer/install.iss =================================================================== --- trunk/OpenMPT/installer/install.iss 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/installer/install.iss 2011-04-03 21:35:05 UTC (rev 840) @@ -45,6 +45,7 @@ #ifdef DOWNLOAD_MO3 Name: downloadmo3; Description: Download unmo3 (library needed for reading MO3 files, recommended); Check: not IsUNMO3Installed; GroupDescription: Options: #endif +Name: update_c; Description: Automatically check for updates; GroupDescription: Options: Name: portable; Description: Portable mode (use program folder for storing settings, no registry changes); GroupDescription: Options:; Flags: unchecked Name: vst_scan; Description: Scan for previously installed VST plugins; GroupDescription: Options:; Flags: unchecked ; file associations - put this below all other [tasks]! @@ -233,6 +234,12 @@ SetIniString('Paths', 'Key_Config_File', keyboardFilepath, INIFile); end; + // Update check + if(not IsTaskSelected('update_c')) then + begin + SetIniString('Update', 'UpdateCheckPeriod', '0', INIFile); + end; + // Scan for pre-installed VST plugins if(IsTaskSelected('vst_scan')) then begin Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-03 21:35:05 UTC (rev 840) @@ -24,6 +24,7 @@ #include <direct.h> #include "version.h" #include "ctrl_pat.h" +#include "UpdateCheck.h" #ifdef _DEBUG #define new DEBUG_NEW @@ -106,6 +107,7 @@ ON_MESSAGE(WM_MOD_INVALIDATEPATTERNS, OnInvalidatePatterns) ON_MESSAGE(WM_MOD_SPECIALKEY, OnSpecialKey) ON_MESSAGE(WM_MOD_KEYCOMMAND, OnCustomKeyMsg) //rewbs.customKeys + ON_COMMAND(ID_INTERNETUPDATE, OnInternetUpdate) //}}AFX_MSG_MAP ON_WM_INITMENU() ON_WM_KILLFOCUS() //rewbs.fix3116 @@ -141,7 +143,7 @@ HHOOK CMainFrame::ghKbdHook = NULL; CString CMainFrame::gcsPreviousVersion = ""; CString CMainFrame::gcsInstallGUID = ""; -int CMainFrame::gnCheckForUpdates = 1; + DWORD CMainFrame::gnHotKeyMask = 0; // Audio Setup //rewbs.resamplerConf @@ -384,7 +386,6 @@ vIniVersion = MptVersion::ToNum(gcsPreviousVersion); gcsInstallGUID = GetPrivateProfileCString("Version", "InstallGUID", "", iniFile); - gnCheckForUpdates = GetPrivateProfileInt("Version", "CheckForUpdates", 1, iniFile); gbMdiMaximize = GetPrivateProfileLong("Display", "MDIMaximize", true, iniFile); glTreeWindowWidth = GetPrivateProfileLong("Display", "MDITreeWidth", 160, iniFile); glTreeSplitRatio = GetPrivateProfileLong("Display", "MDITreeRatio", 128, iniFile); @@ -401,6 +402,27 @@ gnPlugWindowLast = GetPrivateProfileDWord("Display", "PlugSelectWindowLast", 0, iniFile); gnMsgBoxVisiblityFlags = GetPrivateProfileDWord("Display", "MsgBoxVisibilityFlags", uint32_max, iniFile); + // Internet Update + { + tm lastUpdate; + MemsetZero(lastUpdate); + CString s = GetPrivateProfileCString("Update", "LastUpdateCheck", "1970-01-01 00:00", iniFile); + if(sscanf(s, "%04d-%02d-%02d %02d:%02d", &lastUpdate.tm_year, &lastUpdate.tm_mon, &lastUpdate.tm_mday, &lastUpdate.tm_hour, &lastUpdate.tm_min) == 5) + { + lastUpdate.tm_year -= 1900; + lastUpdate.tm_mon--; + } + time_t outTime = _mkgmtime(&lastUpdate); + if(outTime < 0) outTime = 0; + + CUpdateCheck::SetUpdateSettings + ( + outTime, + GetPrivateProfileInt("Update", "UpdateCheckPeriod", CUpdateCheck::GetUpdateCheckPeriod(), iniFile), + GetPrivateProfileCString("Update", "UpdateURL", CUpdateCheck::GetUpdateURL(), iniFile) + ); + } + CHAR s[16]; for (int ncol = 0; ncol < MAX_MODCOLORS; ncol++) { @@ -967,8 +989,7 @@ CString version = MptVersion::str; WritePrivateProfileString("Version", "Version", version, iniFile); WritePrivateProfileString("Version", "InstallGUID", gcsInstallGUID, iniFile); - WritePrivateProfileLong("Version", "CheckForUpdates", gnCheckForUpdates, iniFile); - + WINDOWPLACEMENT wpl; wpl.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(&wpl); @@ -990,8 +1011,22 @@ WritePrivateProfileLong("Display", "PlugSelectWindowLast", gnPlugWindowLast, iniFile); WritePrivateProfileDWord("Display", "MsgBoxVisibilityFlags", gnMsgBoxVisiblityFlags, iniFile); + // Internet Update + { + CString outDate; + const time_t t = CUpdateCheck::GetLastUpdateCheck(); + const tm* const lastUpdate = gmtime(&t); + if(lastUpdate != nullptr) + { + outDate.Format("%04d-%02d-%02d %02d:%02d", lastUpdate->tm_year + 1900, lastUpdate->tm_mon + 1, lastUpdate->tm_mday, lastUpdate->tm_hour, lastUpdate->tm_min); + } + WritePrivateProfileString("Update", "LastUpdateCheck", outDate, iniFile); + WritePrivateProfileDWord("Update", "UpdateCheckPeriod", CUpdateCheck::GetUpdateCheckPeriod(), iniFile); + WritePrivateProfileString("Update", "UpdateURL", CUpdateCheck::GetUpdateURL(), iniFile); + } + CHAR s[16]; - for (int ncol=0; ncol<MAX_MODCOLORS; ncol++) + for (int ncol = 0; ncol < MAX_MODCOLORS; ncol++) { wsprintf(s, "Color%02d", ncol); WritePrivateProfileDWord("Display", s, rgbCustomColors[ncol], iniFile); @@ -2411,6 +2446,7 @@ CMidiSetupDlg mididlg(m_dwMidiSetup, m_nMidiDevice); CEQSetupDlg eqdlg(&m_EqSettings); CAutoSaverGUI autosavedlg(m_pAutoSaver); //rewbs.AutoSaver + CUpdateSetupDlg updatedlg; dlg.AddPage(&general); dlg.AddPage(&sounddlg); dlg.AddPage(&playerdlg); @@ -2419,6 +2455,7 @@ dlg.AddPage(&colors); dlg.AddPage(&mididlg); dlg.AddPage(&autosavedlg); + dlg.AddPage(&updatedlg); m_bOptionsLocked=true; //rewbs.customKeys dlg.DoModal(); m_bOptionsLocked=false; //rewbs.customKeys @@ -3060,6 +3097,14 @@ } +void CMainFrame::OnInternetUpdate() +//--------------------------------- +{ + CUpdateCheck *updateCheck = CUpdateCheck::Create(false); + updateCheck->DoUpdateCheck(); +} + + ///////////////////////////////////////////// //Misc helper functions ///////////////////////////////////////////// Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2011-04-03 21:35:05 UTC (rev 840) @@ -423,7 +423,6 @@ static DWORD gdwNotificationType; static CString gcsPreviousVersion; static CString gcsInstallGUID; - static int gnCheckForUpdates; // Audio Setup static DWORD m_dwSoundSetup, m_dwRate, m_dwQuality, m_nSrcMode, m_nBitsPerSample, m_nPreAmp, gbLoopSong, m_nChannels; @@ -698,6 +697,7 @@ afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM); afx_msg void OnViewMIDIMapping(); afx_msg void OnViewEditHistory(); + afx_msg void OnInternetUpdate(); //}}AFX_MSG DECLARE_MESSAGE_MAP() public: Modified: trunk/OpenMPT/mptrack/Moptions.h =================================================================== --- trunk/OpenMPT/mptrack/Moptions.h 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/Moptions.h 2011-04-03 21:35:05 UTC (rev 840) @@ -13,6 +13,7 @@ OPTIONS_PAGE_COLORS, OPTIONS_PAGE_MIDI, OPTIONS_PAGE_AUTOSAVE, + OPTIONS_PAGE_UPDATE, }; Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2011-04-03 21:35:05 UTC (rev 840) @@ -17,6 +17,7 @@ #include "version.h" #include "test/test.h" #include <shlwapi.h> +#include "UpdateCheck.h" // rewbs.memLeak #define _CRTDBG_MAP_ALLOC @@ -615,10 +616,6 @@ strcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); strcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); CModDoc::CreateZxxFromType(m_MidiCfg.szMidiZXXExt, sfx_fixed_reso4Bit); - - #ifdef UPDATECHECKENABLED - m_pRequestContext = NULL; - #endif } ///////////////////////////////////////////////////////////////////////////// @@ -945,17 +942,11 @@ m_dwTimeStarted = timeGetTime(); m_bInitialized = TRUE; - /* - if (CMainFrame::gnCheckForUpdates) { - try { - UpdateCheck(); - } catch (...) { - // Could not do update check. Don't compain - do nothing. - // Assuming winhttp.dll is set as delay-load in the project settings, - // we will end up here if the dll cannot be foung (e.g. on win98). - } + if (CUpdateCheck::GetUpdateCheckPeriod() != 0) + { + CUpdateCheck *updateCheck = CUpdateCheck::Create(true); + updateCheck->DoUpdateCheck(); } - */ // Open settings if the previous execution was with an earlier version. if (!cmdInfo.m_bNoSettingsOnNewVersion && MptVersion::ToNum(CMainFrame::gcsPreviousVersion) < MptVersion::num) { @@ -974,186 +965,6 @@ } -#ifdef UPDATECHECKENABLED -void __stdcall CTrackApp::InternetRequestCallback( HINTERNET /*hInternet*/, DWORD_PTR userData, DWORD dwInternetStatus, - LPVOID /*lpvStatusInformation*/, DWORD /*dwStatusInformationLength*/) -//----------------------------------------------------------------------------------------------------- -{ - - REQUEST_CONTEXT *pRequestContext = (REQUEST_CONTEXT*)userData; - if (pRequestContext->hRequest == NULL) { - return; - } - - DWORD versionBytesToRead = 10; - - switch (dwInternetStatus) { - case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: - if (!WinHttpReceiveResponse(pRequestContext->hRequest, NULL)) { - CleanupInternetRequest(pRequestContext); - return; - } - break; - case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: - { - DWORD dwDownloaded = 0; - if (!WinHttpQueryDataAvailable(pRequestContext->hRequest, &dwDownloaded)) { - Log("Error %u in WinHttpQueryDataAvailable.\n",GetLastError()); - CleanupInternetRequest(pRequestContext); - return; - } - if (dwDownloaded<versionBytesToRead) { - Log("Downloaded %d bytes, expected at least %d\n", dwDownloaded, versionBytesToRead); - CleanupInternetRequest(pRequestContext); - return; - } - break; - } - case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE: - { - DWORD dwRead = 0; - pRequestContext->lpBuffer = new char[versionBytesToRead+1]; - ZeroMemory(pRequestContext->lpBuffer, versionBytesToRead+1); - - if (!WinHttpReadData(pRequestContext->hRequest, (LPVOID)pRequestContext->lpBuffer, versionBytesToRead, &dwRead)) { - Log("Error %u in WinHttpReadData.\n", GetLastError()); - CleanupInternetRequest(pRequestContext); - return; - } - if (dwRead<versionBytesToRead) { - Log("Read %d bytes, expected at least %d\n", dwRead, versionBytesToRead); - CleanupInternetRequest(pRequestContext); - return; - } - break; - } - case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: - { - CString remoteVersion = pRequestContext->lpBuffer; - CString localVersion = CMainFrame::GetFullVersionString(); - if (remoteVersion > localVersion) { - CString message; - message.Format("New version available: %s (you are using %s). Would you like more information?", remoteVersion, localVersion); - if (AfxMessageBox(message, MB_ICONQUESTION|MB_YESNO ) == IDYES) { - CString URL; - URL.Format("http://openmpt.xwiki.com/xwiki/bin/view/Development/Builds?currentVersion=%s", localVersion); - CTrackApp::OpenURL(URL); - } - } - CleanupInternetRequest(pRequestContext); - break; - } - default: - Log("Unhandled callback - status %d given", dwInternetStatus); - break; - } - -} - -void CTrackApp::CleanupInternetRequest(REQUEST_CONTEXT *pRequestContext) -//------------------------------------------------------------------------- -{ - if (pRequestContext != NULL) { - if (pRequestContext->lpBuffer != NULL) { - delete[] pRequestContext->lpBuffer; - pRequestContext->lpBuffer = NULL; - } - - if (pRequestContext->postData != NULL) { - delete[] pRequestContext->postData; - pRequestContext->postData = NULL; - } - - if (pRequestContext->hRequest != NULL) { - WinHttpSetStatusCallback(pRequestContext->hRequest, NULL, NULL, NULL); - WinHttpCloseHandle(pRequestContext->hRequest); - pRequestContext->hRequest = NULL; - } - - if (pRequestContext->hConnection != NULL) { - WinHttpCloseHandle(pRequestContext->hConnection); - pRequestContext->hConnection = NULL; - } - - if (pRequestContext->hSession != NULL) { - WinHttpCloseHandle(pRequestContext->hSession); - pRequestContext->hSession = NULL; - } - } -} - -void CTrackApp::UpdateCheck() -//--------------------------- -{ - m_pRequestContext = new REQUEST_CONTEXT(); - m_pRequestContext->hSession = NULL; - m_pRequestContext->hConnection = NULL; - m_pRequestContext->hRequest = NULL; - m_pRequestContext->lpBuffer = NULL; - m_pRequestContext->postData = NULL; - - // Prepare post data - if (CMainFrame::gcsInstallGUID == "") { - //No GUID found in INI file - generate one. - GUID guid; - CoCreateGuid(&guid); - BYTE* Str; - UuidToString((UUID*)&guid, &Str); - CMainFrame::gcsInstallGUID.Format("%s", (LPTSTR)Str); - RpcStringFree(&Str); - } - - CString csPostData; - csPostData.Format("install_id=%s&install_version=%s", CMainFrame::gcsInstallGUID, CMainFrame::GetFullVersionString()); - int length = csPostData.GetLength(); - m_pRequestContext->postData = new char[length+1]; - strcpy(m_pRequestContext->postData, csPostData); - - m_pRequestContext->hSession = WinHttpOpen( L"OpenMPT/1.17", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, - WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC); - if (m_pRequestContext->hSession==NULL) { - CleanupInternetRequest(m_pRequestContext); - return; - } - - m_pRequestContext->hConnection = WinHttpConnect(m_pRequestContext->hSession, L"www.soal.org", INTERNET_DEFAULT_HTTP_PORT, 0); - if (m_pRequestContext->hConnection==NULL) { - CleanupInternetRequest(m_pRequestContext); - return; - } - - m_pRequestContext->hRequest = WinHttpOpenRequest(m_pRequestContext->hConnection, L"POST", L"openmpt/OpenMPTversionCheck.php5", - NULL, NULL, NULL, 0); - if (m_pRequestContext->hRequest==NULL) { - CleanupInternetRequest(m_pRequestContext); - return; - } - - if (!WinHttpAddRequestHeaders(m_pRequestContext->hRequest, L"Content-Type:application/x-www-form-urlencoded\r\n\r\n", - -1L, WINHTTP_ADDREQ_FLAG_ADD)) { - CleanupInternetRequest(m_pRequestContext); - return; - } - - WINHTTP_STATUS_CALLBACK pCallback = WinHttpSetStatusCallback(m_pRequestContext->hRequest, - static_cast<WINHTTP_STATUS_CALLBACK>(InternetRequestCallback), - WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, - NULL); - if (pCallback == WINHTTP_INVALID_STATUS_CALLBACK) { - Log("Error %d in WinHttpSetStatusCallback.\n", WINHTTP_INVALID_STATUS_CALLBACK); - CleanupInternetRequest(m_pRequestContext); - return; - } - - if (!WinHttpSendRequest(m_pRequestContext->hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, m_pRequestContext->postData, length, length, (DWORD_PTR)m_pRequestContext)) { - CleanupInternetRequest(m_pRequestContext); - return; - } -} - -#endif - - int CTrackApp::ExitInstance() //--------------------------- { @@ -1205,12 +1016,6 @@ // Uninitialize ACM UninitializeACM(); - // Cleanup the internet request, in case it is still active. - #ifdef UPDATECHECKENABLED - CleanupInternetRequest(m_pRequestContext); - delete m_pRequestContext; - #endif - return CWinApp::ExitInstance(); } Modified: trunk/OpenMPT/mptrack/Mptrack.h =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.h 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/Mptrack.h 2011-04-03 21:35:05 UTC (rev 840) @@ -16,11 +16,6 @@ #include "../soundlib/Sndfile.h" #include <windows.h> -#ifdef UPDATECHECKENABLED - #include <Specstrings.h> // In VC2003, '__in' was undefined in winhttp.h - #include <winhttp.h> -#endif - class CModDoc; class CVstPluginManager; @@ -101,20 +96,6 @@ ///////////////////////////////////////////////////////////////////////////// -// Internet connection context - -#ifdef UPDATECHECKENABLED -typedef struct REQUEST_CONTEXT { - HINTERNET hSession; - HINTERNET hConnection; - HINTERNET hRequest; - LPSTR lpBuffer; // Buffer for storing read data - LPSTR postData; -} REQUEST_CONTEXT; -#endif - - -///////////////////////////////////////////////////////////////////////////// // File dialog (open/save) results struct FileDlgResult { @@ -161,11 +142,6 @@ TCHAR m_szStringsFileName[_MAX_PATH]; static bool m_bPortableMode; - #ifdef UPDATECHECKENABLED - // Internet request context - REQUEST_CONTEXT *m_pRequestContext; - #endif - public: CTrackApp(); @@ -213,13 +189,6 @@ VOID StartSplashScreen(); VOID StopSplashScreen(); - #ifdef UPDATECHECKENABLED - VOID UpdateCheck(); - static void __stdcall InternetRequestCallback( HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, - LPVOID lpvStatusInformation, DWORD dwStatusInformationLength); - static void CleanupInternetRequest(REQUEST_CONTEXT *pRequestContext); - #endif - // Localized strings public: VOID ImportLocalizedStrings(); Added: trunk/OpenMPT/mptrack/UpdateCheck.cpp =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.cpp (rev 0) +++ trunk/OpenMPT/mptrack/UpdateCheck.cpp 2011-04-03 21:35:05 UTC (rev 840) @@ -0,0 +1,325 @@ +/* + * UpdateCheck.cpp + * --------------- + * Purpose: Class for easy software update check. + * Notes : (currently none) + * Authors: OpenMPT Devs + */ + +#include "stdafx.h" +#include "UpdateCheck.h" +#include "version.h" +#include "misc_util.h" +#include "Mptrack.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +// Static configuration variables +time_t CUpdateCheck::lastUpdateCheck = 0; +int CUpdateCheck::updateCheckPeriod = 7; +CString CUpdateCheck::updateBaseURL = "http://update.openmpt.org/check/%s"; + + +CUpdateCheck::CUpdateCheck(const bool autoUpdate) +//----------------------------------------------- +{ + isAutoUpdate = autoUpdate; + threadHandle = NULL; +} + + +CUpdateCheck::~CUpdateCheck() +//--------------------------- +{ + if(threadHandle != NULL) + { + CloseHandle(threadHandle); + } +} + + +// Start update check +void CUpdateCheck::DoUpdateCheck() +//-------------------------------- +{ + internetHandle = NULL; + connectionHandle = NULL; + + DWORD dummy; // For Win9x + threadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&CUpdateCheck::UpdateThread, (LPVOID)this, 0, &dummy); + if(isAutoUpdate) + { + SetThreadPriority(threadHandle, THREAD_PRIORITY_BELOW_NORMAL); + } +} + + +// Run update check (independent thread) +DWORD WINAPI CUpdateCheck::UpdateThread(LPVOID param) +//--------------------------------------------------- +{ + CUpdateCheck *caller = (CUpdateCheck *)param; + + const time_t now = time(nullptr); + + if(caller->isAutoUpdate) + { + // Do we actually need to run the update check right now? + if(CUpdateCheck::updateCheckPeriod == 0 || difftime(now, CUpdateCheck::lastUpdateCheck) < (double)(CUpdateCheck::updateCheckPeriod * 86400)) + { + caller->Terminate(); + return 0; + } + } + + const CString userAgent = CString("OpenMPT ") + MptVersion::str; + CString updateURL; + updateURL.Format(CUpdateCheck::updateBaseURL, MptVersion::str); + + /*if (CMainFrame::gcsInstallGUID == "") + { + //No GUID found in INI file - generate one. + GUID guid; + CoCreateGuid(&guid); + BYTE* Str; + UuidToString((UUID*)&guid, &Str); + CMainFrame::gcsInstallGUID.Format("%s", (LPTSTR)Str); + RpcStringFree(&Str); + }*/ + + // Establish a connection. + caller->internetHandle = InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + if(caller->internetHandle == NULL) + { + caller->Die("Could not start update check:\n", GetLastError()); + return 0; + } + caller->connectionHandle = InternetOpenUrl(caller->internetHandle, updateURL, NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_UI, 0); + if(caller->connectionHandle == NULL) + { + caller->Die("Could not establish connection:\n", GetLastError()); + return 0; + } + + // Retrieve HTTP status code. + DWORD statusCodeHTTP = 0; + DWORD length = sizeof(statusCodeHTTP); + if(HttpQueryInfo(caller->connectionHandle, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&statusCodeHTTP, &length, NULL) == FALSE) + { + caller->Die("Could not retrieve HTTP header information:\n", GetLastError()); + return 0; + } + if(statusCodeHTTP >= 400) + { + CString error; + error.Format("Version information could not be found on the server (HTTP status code %d). Maybe your version of OpenMPT is too old!", statusCodeHTTP); + caller->Die(error); + return 0; + } + + // Download data. + CString resultData = ""; + char *downloadBuffer = new char[DOWNLOAD_BUFFER_SIZE]; + DWORD availableSize = 0, bytesRead = 0; + do + { + if(InternetQueryDataAvailable(caller->connectionHandle, &availableSize, 0, NULL) == FALSE) + { + caller->Die("Error while downloading update information data:\n", GetLastError()); + } + + LimitMax(availableSize, (DWORD)DOWNLOAD_BUFFER_SIZE); + + if(InternetReadFile(caller->connectionHandle, downloadBuffer, availableSize, &bytesRead) == FALSE) + { + caller->Die("Error while downloading update information data:\n", GetLastError()); + } + + resultData.Append(downloadBuffer, availableSize); + } while(bytesRead != 0); + delete[] downloadBuffer; + + // Now, evaluate the downloaded data. + if(!resultData.CompareNoCase("noupdate")) + { + if(!caller->isAutoUpdate) + { + ::MessageBox(0, "You already have the latest version of OpenMPT.", "OpenMPT Internet Update", MB_OK | MB_ICONINFORMATION); + } + } else + { + CString releaseVersion, releaseDate, releaseURL; + CString token; + int parseStep = 0, parsePos = 0; + while((token = resultData.Tokenize("\n", parsePos)) != "") + { + token.Trim(); + switch(parseStep++) + { + case 0: + if(token.CompareNoCase("update") != 0) + { + caller->Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); + return 0; + } + break; + case 1: + releaseVersion = token; + break; + case 2: + releaseDate = token; + break; + case 3: + releaseURL = token; + break; + } + } + if(parseStep >= 4) + { + resultData.Format("A new version is available!\nOpenMPT %s has been released on %s. Would you like to visit %s for more information?", releaseVersion, releaseDate, releaseURL); + if(::MessageBox(0, resultData, "OpenMPT Internet Update", MB_YESNO | MB_ICONINFORMATION) == IDYES) + { + CTrackApp::OpenURL(releaseURL); + } + } else + { + caller->Die("Could not understand server response. Maybe your version of OpenMPT is too old!"); + return 0; + } + } + + CUpdateCheck::lastUpdateCheck = now; + + caller->Terminate(); + return 0; +} + + +// Die with error message +void CUpdateCheck::Die(CString errorMessage) +//------------------------------------------ +{ + if(!isAutoUpdate) + { + ::MessageBox(0, errorMessage, "OpenMPT Internet Update Error", MB_OK | MB_ICONERROR); + } + Terminate(); +} + + +// Die with WinINet error message +void CUpdateCheck::Die(CString errorMessage, DWORD errorCode) +//----------------------------------------------------------- +{ + if(!isAutoUpdate) + { + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + GetModuleHandle(TEXT("wininet.dll")), errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); + + errorMessage.Append((LPTSTR)lpMsgBuf); + LocalFree(lpMsgBuf); + } + Die(errorMessage); +} + + +// Kill update object +void CUpdateCheck::Terminate() +//---------------------------- +{ + if(connectionHandle != NULL) + { + InternetCloseHandle(connectionHandle); + connectionHandle = NULL; + } + if(internetHandle != NULL) + { + InternetCloseHandle(internetHandle); + internetHandle = NULL; + } + threadHandle = NULL; // If we got here, the thread asked for termination, so don't use CloseHandle() + delete this; +} + + +///////////////////////////////////////////////////////////// +// CUpdateSetupDlg + +BEGIN_MESSAGE_MAP(CUpdateSetupDlg, CPropertyPage) + ON_COMMAND(IDC_BUTTON1, OnCheckNow) + ON_COMMAND(IDC_RADIO1, OnSettingsChanged) + ON_COMMAND(IDC_RADIO2, OnSettingsChanged) + ON_COMMAND(IDC_RADIO3, OnSettingsChanged) + ON_COMMAND(IDC_RADIO4, OnSettingsChanged) + ON_EN_CHANGE(IDC_EDIT1, OnSettingsChanged) +END_MESSAGE_MAP() + + +BOOL CUpdateSetupDlg::OnInitDialog() +//---------------------------------- +{ + CPropertyPage::OnInitDialog(); + + int radioID = 0; + switch(CUpdateCheck::GetUpdateCheckPeriod()) + { + case 0: radioID = IDC_RADIO1; break; + case 1: radioID = IDC_RADIO2; break; + case 7: radioID = IDC_RADIO3; break; + case 31: radioID = IDC_RADIO4; break; + } + CheckRadioButton(IDC_RADIO1, IDC_RADIO4, radioID); + SetDlgItemText(IDC_EDIT1, CUpdateCheck::GetUpdateURL()); + + const time_t t = CUpdateCheck::GetLastUpdateCheck(); + if(t > 0) + { + CString updateText; + const tm* const lastUpdate = localtime(&t); + if(lastUpdate != nullptr) + { + updateText.Format("The last successful update check was run on %04d-%02d-%02d, %02d:%02d.", lastUpdate->tm_year + 1900, lastUpdate->tm_mon + 1, lastUpdate->tm_mday, lastUpdate->tm_hour, lastUpdate->tm_min); + SetDlgItemText(IDC_LASTUPDATE, updateText); + } + } + + return TRUE; +} + + +void CUpdateSetupDlg::OnOK() +//-------------------------- +{ + int updateCheckPeriod = CUpdateCheck::GetUpdateCheckPeriod(); + if(IsDlgButtonChecked(IDC_RADIO1)) updateCheckPeriod = 0; + if(IsDlgButtonChecked(IDC_RADIO2)) updateCheckPeriod = 1; + if(IsDlgButtonChecked(IDC_RADIO3)) updateCheckPeriod = 7; + if(IsDlgButtonChecked(IDC_RADIO4)) updateCheckPeriod = 31; + + CString updateURL; + GetDlgItemText(IDC_EDIT1, updateURL); + CUpdateCheck::SetUpdateSettings(CUpdateCheck::GetLastUpdateCheck(), updateCheckPeriod, updateURL); + + CPropertyPage::OnOK(); +} + + +BOOL CUpdateSetupDlg::OnSetActive() +//--------------------------------- +{ + CMainFrame::m_nLastOptionsPage = OPTIONS_PAGE_UPDATE; + return CPropertyPage::OnSetActive(); +} + + +void CUpdateSetupDlg::OnCheckNow() +//-------------------------------- +{ + CUpdateCheck *updateCheck = CUpdateCheck::Create(false); + updateCheck->DoUpdateCheck(); +} + Added: trunk/OpenMPT/mptrack/UpdateCheck.h =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.h (rev 0) +++ trunk/OpenMPT/mptrack/UpdateCheck.h 2011-04-03 21:35:05 UTC (rev 840) @@ -0,0 +1,80 @@ +/* + * UpdateCheck.h + * ------------- + * Purpose: Header for easy software update check. + * Notes : (currently none) + * Authors: OpenMPT Devs + */ + +#pragma once +#ifndef UPDATECHECK_H +#define UPDATECHECK_H + +#include <WinInet.h> +#include <time.h> + +// Setup dialog stuff +#include "Mainfrm.h" +#include "resource.h" +#include "Moptions.h" + + +#define DOWNLOAD_BUFFER_SIZE 256 + +//================ +class CUpdateCheck +//================ +{ +public: + + // Force creation via "new" as we're using "delete this". + static CUpdateCheck *Create(bool autoUpdate) { return new CUpdateCheck(autoUpdate); }; + void DoUpdateCheck(); + + static time_t GetLastUpdateCheck() { return lastUpdateCheck; }; + static int GetUpdateCheckPeriod() { return updateCheckPeriod; }; + static CString GetUpdateURL() { return updateBaseURL; }; + static void SetUpdateSettings(time_t last, int period, CString url) { lastUpdateCheck = last; updateCheckPeriod = period; updateBaseURL = url; }; + +protected: + + // Static configuration variables + static time_t lastUpdateCheck; // Time of last successful update check + static int updateCheckPeriod; // Check for updates every x days + static CString updateBaseURL; // URL where the version check should be made. + + bool isAutoUpdate; // Are we running an automatic update check? + + // Runtime resource handles + HANDLE threadHandle; + HINTERNET internetHandle, connectionHandle; + + CUpdateCheck(const bool showErrors); + ~CUpdateCheck(); + + static DWORD WINAPI UpdateThread(LPVOID param); + void Die(CString errorMessage); + void Die(CString errorMessage, DWORD errorCode); + void Terminate(); +}; + + +//========================================= +class CUpdateSetupDlg: public CPropertyPage +//========================================= +{ +public: + CUpdateSetupDlg():CPropertyPage(IDD_OPTIONS_UPDATE) + { }; + +protected: + virtual BOOL OnInitDialog(); + virtual void OnOK(); + virtual BOOL OnSetActive(); + afx_msg void OnSettingsChanged() { SetModified(TRUE); } + afx_msg void OnCheckNow(); + DECLARE_MESSAGE_MAP() +}; + +#endif // UPDATECHECK_H + Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/mptrack.rc 2011-04-03 21:35:05 UTC (rev 840) @@ -186,7 +186,25 @@ LTEXT "Samples used for fading:",IDC_STATIC,6,8,96,8 END +IDD_OPTIONS_UPDATE DIALOGEX 0, 0, 274, 281 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Update" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Check for Updates",IDC_STATIC,6,6,258,66 + CONTROL "Never",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,12,18,240,8 + CONTROL "Daily",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,12,30,240,8 + CONTROL "Weekly (recommended)",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,12,42,240,8 + CONTROL "Monthly",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,12,54,240,8 + GROUPBOX "Advanced Settings",IDC_STATIC,6,78,258,60 + LTEXT "Update server URL:",IDC_STATIC,12,90,246,8 + EDITTEXT IDC_EDIT1,12,102,246,12,ES_AUTOHSCROLL + LTEXT "",IDC_LASTUPDATE,6,168,258,24 + LTEXT "Do not change this unless you are absolutely sure of what you are doing.",IDC_STATIC,12,120,246,12 + PUSHBUTTON "Check for Updates",IDC_BUTTON1,6,144,84,18 +END + ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO @@ -266,6 +284,14 @@ TOPMARGIN, 7 BOTTOMMARGIN, 75 END + + IDD_OPTIONS_UPDATE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 267 + TOPMARGIN, 7 + BOTTOMMARGIN, 274 + END END #endif // APSTUDIO_INVOKED @@ -2035,6 +2061,7 @@ MENUITEM "&OpenMPT Website", ID_NETLINK_MODPLUG MENUITEM "&Web Resources", ID_NETLINK_TOP_PICKS MENUITEM SEPARATOR + MENUITEM "Check for &Updates...", ID_INTERNETUPDATE MENUITEM "&About OpenMPT...", ID_APP_ABOUT END END @@ -2750,6 +2777,7 @@ BEGIN MENUITEM "&Load Preset...", ID_PRESET_LOAD MENUITEM "&Save Preset As...", ID_PRESET_SAVE + MENUITEM "Create instrument from plugin", ID_PLUGINTOINSTRUMENT MENUITEM SEPARATOR MENUITEM "&Randomize Params", ID_PRESET_RANDOM END Modified: trunk/OpenMPT/mptrack/mptrack.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack.vcproj 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/mptrack.vcproj 2011-04-03 21:35:05 UTC (rev 840) @@ -126,7 +126,7 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="winmm.lib strmiids.lib dmoguids.lib version.lib opengl32.lib glu32.lib Rpcrt4.lib delayimp.lib" + AdditionalDependencies="winmm.lib strmiids.lib dmoguids.lib version.lib opengl32.lib glu32.lib Rpcrt4.lib delayimp.lib wininet.lib" OutputFile=".\Bin/mptrack.exe" Version="5.0" LinkIncremental="1" @@ -427,6 +427,9 @@ RelativePath=".\Undo.cpp"> </File> <File + RelativePath=".\UpdateCheck.cpp"> + </File> + <File RelativePath=".\view_com.cpp"> </File> <File @@ -840,6 +843,9 @@ RelativePath=".\Undo.h"> </File> <File + RelativePath=".\UpdateCheck.h"> + </File> + <File RelativePath=".\version.h"> </File> <File Modified: trunk/OpenMPT/mptrack/mptrack_08.vcproj =================================================================== --- trunk/OpenMPT/mptrack/mptrack_08.vcproj 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/mptrack_08.vcproj 2011-04-03 21:35:05 UTC (rev 840) @@ -189,7 +189,7 @@ <Tool Name="VCLinkerTool" AdditionalOptions="/MACHINE:I386" - AdditionalDependencies="winmm.lib strmiids.lib dmoguids.lib version.lib opengl32.lib glu32.lib Rpcrt4.lib delayimp.lib" + AdditionalDependencies="winmm.lib strmiids.lib dmoguids.lib version.lib opengl32.lib glu32.lib Rpcrt4.lib delayimp.lib wininet.lib" OutputFile=".\Bin/mptrack.exe" Version="5.0" LinkIncremental="1" @@ -573,6 +573,10 @@ > </File> <File + RelativePath=".\UpdateCheck.cpp" + > + </File> + <File RelativePath=".\view_com.cpp" > </File> @@ -1119,6 +1123,10 @@ > </File> <File + RelativePath=".\UpdateCheck.h" + > + </File> + <File RelativePath=".\version.h" > </File> Modified: trunk/OpenMPT/mptrack/resource.h =================================================================== --- trunk/OpenMPT/mptrack/resource.h 2011-04-01 15:43:38 UTC (rev 839) +++ trunk/OpenMPT/mptrack/resource.h 2011-04-03 21:35:05 UTC (rev 840) @@ -138,6 +138,7 @@ #define IDD_EDITHISTORY 526 #define IDD_SAMPLE_GRID_SIZE 527 #define IDD_SAMPLE_XFADE 528 +#define IDD_OPTIONS_UPDATE 529 #define IDC_BUTTON1 1001 #define IDC_BUTTON2 1002 #define IDC_BUTTON3 1003 @@ -930,6 +931,7 @@ #define IDC_EDIT_HISTORY 2432 #define IDC_SAMPLE_QUICKFADE 2433 #define IDC_SAMPLE_XFADE 2434 +#define IDC_LASTUPDATE 2435 #define ID_FILE_NEWMOD 32771 #define ID_FILE_NEWXM 32772 #define ID_FILE_NEWS3M 32773 @@ -1186,15 +1188,16 @@ #define ID_EDIT_MIXPASTE_ITSTYLE 60455 #define ID_VIEW_MPTHACKS 60456 #define ID_PLUGINTOINSTRUMENT 60457 +#define ID_INTERNETUPDATE 60458 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 529 -#define _APS_NEXT_COMMAND_VALUE 60458 -#define _APS_NEXT_CONTROL_VALUE 2435 +#define _APS_NEXT_RESOURCE_VALUE 530 +#define _APS_NEXT_COMMAND_VALUE 60459 +#define _APS_NEXT_CONTROL_VALUE 2436 #define _APS_NEXT_SYMED_VALUE 901 #endif #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-05 13:03:27
|
Revision: 841 http://modplug.svn.sourceforge.net/modplug/?rev=841&view=rev Author: saga-games Date: 2011-04-05 13:03:17 +0000 (Tue, 05 Apr 2011) Log Message: ----------- [Mod] Update Check: On first run, a hint is shown so people don't have to wonder what their firewall is doing. [Mod] Colour Setup: Changed order of channel separator colours. Modified Paths: -------------- trunk/OpenMPT/installer/install.iss trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Moptions.cpp trunk/OpenMPT/mptrack/UpdateCheck.cpp trunk/OpenMPT/mptrack/UpdateCheck.h Modified: trunk/OpenMPT/installer/install.iss =================================================================== --- trunk/OpenMPT/installer/install.iss 2011-04-03 21:35:05 UTC (rev 840) +++ trunk/OpenMPT/installer/install.iss 2011-04-05 13:03:17 UTC (rev 841) @@ -238,6 +238,10 @@ if(not IsTaskSelected('update_c')) then begin SetIniString('Update', 'UpdateCheckPeriod', '0', INIFile); + end else + begin + SetIniString('Update', 'UpdateCheckPeriod', '7', INIFile); + //SetIniString('Update', 'LastUpdateCheck', GetDateTimeString('yyyy-mm-dd hh:nn', #0, #0), INIFile); end; // Scan for pre-installed VST plugins Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-03 21:35:05 UTC (rev 840) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-05 13:03:17 UTC (rev 841) @@ -419,7 +419,8 @@ ( outTime, GetPrivateProfileInt("Update", "UpdateCheckPeriod", CUpdateCheck::GetUpdateCheckPeriod(), iniFile), - GetPrivateProfileCString("Update", "UpdateURL", CUpdateCheck::GetUpdateURL(), iniFile) + GetPrivateProfileCString("Update", "UpdateURL", CUpdateCheck::GetUpdateURL(), iniFile), + GetPrivateProfileInt("Update", "ShowUpdateHint", CUpdateCheck::GetShowUpdateHint() ? 1 : 0, iniFile) ? true : false ); } @@ -1021,8 +1022,9 @@ outDate.Format("%04d-%02d-%02d %02d:%02d", lastUpdate->tm_year + 1900, lastUpdate->tm_mon + 1, lastUpdate->tm_mday, lastUpdate->tm_hour, lastUpdate->tm_min); } WritePrivateProfileString("Update", "LastUpdateCheck", outDate, iniFile); - WritePrivateProfileDWord("Update", "UpdateCheckPeriod", CUpdateCheck::GetUpdateCheckPeriod(), iniFile); + WritePrivateProfileLong("Update", "UpdateCheckPeriod", CUpdateCheck::GetUpdateCheckPeriod(), iniFile); WritePrivateProfileString("Update", "UpdateURL", CUpdateCheck::GetUpdateURL(), iniFile); + WritePrivateProfileLong("Update", "ShowUpdateHint", CUpdateCheck::GetShowUpdateHint() ? 1 : 0, iniFile); } CHAR s[16]; Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2011-04-03 21:35:05 UTC (rev 840) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2011-04-05 13:03:17 UTC (rev 841) @@ -29,14 +29,13 @@ {"Note Highlight", 0, MODCOLOR_NOTE, MODCOLOR_INSTRUMENT, MODCOLOR_VOLUME, "Note:", "Instrument:", "Volume:"}, {"Effect Highlight",0, MODCOLOR_PANNING, MODCOLOR_PITCH, MODCOLOR_GLOBALS, "Panning Effects:", "Pitch Effects:", "Global Effects:"}, {"Invalid Commands",0, MODCOLOR_DODGY_COMMANDS, 0, 0, "Invalid Note:", NULL, NULL}, - {"Channel Separator",0, MODCOLOR_SEPSHADOW, MODCOLOR_SEPFACE, MODCOLOR_SEPHILITE, "Shadow:", "Face:", "Highlight:"}, + {"Channel Separator",0, MODCOLOR_SEPHILITE, MODCOLOR_SEPFACE, MODCOLOR_SEPSHADOW, "Highlight:", "Face:", "Shadow:"}, {"Next/Prev Pattern",0, MODCOLOR_BLENDCOLOR, 0, 0, "Blend color:", NULL, NULL}, {"Sample Editor", 1, MODCOLOR_SAMPLE, 0, 0, "Sample Data:", NULL, NULL}, {"Instrument Editor",2, MODCOLOR_ENVELOPES, 0, 0, "Envelopes:", NULL, NULL}, {"VU-Meters", 0, MODCOLOR_VUMETER_HI, MODCOLOR_VUMETER_MED, MODCOLOR_VUMETER_LO, "Hi:", "Med:", "Lo:"} }; -#define NUMCOLORDEFS (sizeof(gColorDefs)/sizeof(MPTCOLORDEF)) #define PREVIEWBMP_WIDTH 88 #define PREVIEWBMP_HEIGHT 39 @@ -85,7 +84,7 @@ CPropertyPage::OnInitDialog(); m_pPreviewDib = LoadDib(MAKEINTRESOURCE(IDB_COLORSETUP)); memcpy(CustomColors, CMainFrame::rgbCustomColors, sizeof(CustomColors)); - for (UINT i=0; i<NUMCOLORDEFS; i++) + for (UINT i = 0; i < CountOf(gColorDefs); i++) { m_ComboItem.SetItemData(m_ComboItem.AddString(gColorDefs[i].pszName), i); } Modified: trunk/OpenMPT/mptrack/UpdateCheck.cpp =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.cpp 2011-04-03 21:35:05 UTC (rev 840) +++ trunk/OpenMPT/mptrack/UpdateCheck.cpp 2011-04-05 13:03:17 UTC (rev 841) @@ -21,6 +21,7 @@ time_t CUpdateCheck::lastUpdateCheck = 0; int CUpdateCheck::updateCheckPeriod = 7; CString CUpdateCheck::updateBaseURL = "http://update.openmpt.org/check/%s"; +bool CUpdateCheck::showUpdateHint = true; CUpdateCheck::CUpdateCheck(const bool autoUpdate) @@ -73,7 +74,22 @@ caller->Terminate(); return 0; } + + // Never ran update checks before, so we notify the user of automatic update checks. + if(CUpdateCheck::showUpdateHint) + { + CString msg; + msg.Format("OpenMPT would like to check for updates now, proceed?\n\nNote: In the future, OpenMPT will check for updates every %d days. If you do not want this, you can disable update checks in the setup.", CUpdateCheck::updateCheckPeriod); + if(::MessageBox(0, msg, "OpenMPT Internet Update", MB_YESNO | MB_ICONQUESTION) == IDNO) + { + CUpdateCheck::showUpdateHint = false; + caller->Terminate(); + return 0; + } + + } } + CUpdateCheck::showUpdateHint = false; const CString userAgent = CString("OpenMPT ") + MptVersion::str; CString updateURL; @@ -123,9 +139,10 @@ // Download data. CString resultData = ""; char *downloadBuffer = new char[DOWNLOAD_BUFFER_SIZE]; - DWORD availableSize = 0, bytesRead = 0; + DWORD availableSize, bytesRead; do { + // Query number of available bytes to download if(InternetQueryDataAvailable(caller->connectionHandle, &availableSize, 0, NULL) == FALSE) { caller->Die("Error while downloading update information data:\n", GetLastError()); @@ -133,12 +150,15 @@ LimitMax(availableSize, (DWORD)DOWNLOAD_BUFFER_SIZE); + // Put downloaded bytes into our buffer if(InternetReadFile(caller->connectionHandle, downloadBuffer, availableSize, &bytesRead) == FALSE) { caller->Die("Error while downloading update information data:\n", GetLastError()); } resultData.Append(downloadBuffer, availableSize); + Sleep(1); + } while(bytesRead != 0); delete[] downloadBuffer; @@ -302,7 +322,7 @@ CString updateURL; GetDlgItemText(IDC_EDIT1, updateURL); - CUpdateCheck::SetUpdateSettings(CUpdateCheck::GetLastUpdateCheck(), updateCheckPeriod, updateURL); + CUpdateCheck::SetUpdateSettings(CUpdateCheck::GetLastUpdateCheck(), updateCheckPeriod, updateURL, CUpdateCheck::GetShowUpdateHint()); CPropertyPage::OnOK(); } @@ -319,7 +339,6 @@ void CUpdateSetupDlg::OnCheckNow() //-------------------------------- { - CUpdateCheck *updateCheck = CUpdateCheck::Create(false); - updateCheck->DoUpdateCheck(); + CMainFrame::GetMainFrame()->PostMessage(WM_COMMAND, ID_INTERNETUPDATE); } Modified: trunk/OpenMPT/mptrack/UpdateCheck.h =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.h 2011-04-03 21:35:05 UTC (rev 840) +++ trunk/OpenMPT/mptrack/UpdateCheck.h 2011-04-05 13:03:17 UTC (rev 841) @@ -34,7 +34,9 @@ static time_t GetLastUpdateCheck() { return lastUpdateCheck; }; static int GetUpdateCheckPeriod() { return updateCheckPeriod; }; static CString GetUpdateURL() { return updateBaseURL; }; - static void SetUpdateSettings(time_t last, int period, CString url) { lastUpdateCheck = last; updateCheckPeriod = period; updateBaseURL = url; }; + static bool GetShowUpdateHint() { return showUpdateHint; }; + static void SetUpdateSettings(time_t last, int period, CString url, bool showHint) + { lastUpdateCheck = last; updateCheckPeriod = period; updateBaseURL = url; showUpdateHint = showHint; }; protected: @@ -42,6 +44,7 @@ static time_t lastUpdateCheck; // Time of last successful update check static int updateCheckPeriod; // Check for updates every x days static CString updateBaseURL; // URL where the version check should be made. + static bool showUpdateHint; // Show hint on first automatic update bool isAutoUpdate; // Are we running an automatic update check? This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-08 22:23:26
|
Revision: 842 http://modplug.svn.sourceforge.net/modplug/?rev=842&view=rev Author: saga-games Date: 2011-04-08 22:23:19 +0000 (Fri, 08 Apr 2011) Log Message: ----------- [Reg] Removed hidden INI flag to suppress warnings when encountering keymaps with unknown items. This option made sense when such files threw multiple message boxes, but now it's just one and it shouldn't be ignored... [Fix] Note Properties: Axx is not limited to value 7F anymore for IT/S3M. [Imp] Mod Conversion: Improved of Sxx (IT/S3M) and PC Notes. Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/CommandSet.h trunk/OpenMPT/mptrack/InputHandler.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/soundlib/modcommand.cpp Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2011-04-05 13:03:17 UTC (rev 841) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2011-04-08 22:23:19 UTC (rev 842) @@ -16,8 +16,6 @@ #endif -bool CCommandSet::s_bShowErrorOnUnknownKeybinding = true; - CCommandSet::CCommandSet(void) { // Which keybinding rules to enforce? @@ -1579,7 +1577,7 @@ l++; } - if(s_bShowErrorOnUnknownKeybinding && !errText.IsEmpty()) + if(!errText.IsEmpty()) { CString err; err.Format("The following problems have been encountered while trying to load the key binding file %s:\n", szFilename); Modified: trunk/OpenMPT/mptrack/CommandSet.h =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.h 2011-04-05 13:03:17 UTC (rev 841) +++ trunk/OpenMPT/mptrack/CommandSet.h 2011-04-08 22:23:19 UTC (rev 842) @@ -1166,7 +1166,6 @@ bool enforceRule[kNumRules]; public: - static bool s_bShowErrorOnUnknownKeybinding; CCommandSet(void); ~CCommandSet(void); Modified: trunk/OpenMPT/mptrack/InputHandler.cpp =================================================================== --- trunk/OpenMPT/mptrack/InputHandler.cpp 2011-04-05 13:03:17 UTC (rev 841) +++ trunk/OpenMPT/mptrack/InputHandler.cpp 2011-04-08 22:23:19 UTC (rev 842) @@ -21,7 +21,6 @@ //Init CommandSet and Load defaults activeCommandSet = new CCommandSet(); - CCommandSet::s_bShowErrorOnUnknownKeybinding = (CMainFrame::GetMainFrame()->GetPrivateProfileLong("Misc", "ShowErrorOnUnknownKeybinding", 1, theApp.GetConfigFileName()) != 0); CString sDefaultPath = CString(theApp.GetConfigPath()) + TEXT("Keybindings.mkb"); if (sDefaultPath.GetLength() > MAX_PATH - 1) Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-05 13:03:17 UTC (rev 841) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-08 22:23:19 UTC (rev 842) @@ -2432,7 +2432,7 @@ break; case CMD_SPEED: nmin = 1; - nmax = 0x7F; + nmax = 0xFF; if (nType & MOD_TYPE_MOD) nmax = 0x20; else if (nType & MOD_TYPE_XM) nmax = 0x1F; break; @@ -3074,7 +3074,7 @@ case VOLCMD_PANNING: *prangeMax = 64; - if (m_SndFile.m_nType & MOD_TYPE_XM) + if (m_SndFile.GetType() & MOD_TYPE_XM) { *prangeMin = 2; // 0*4+2 *prangeMax = 62; // 15*4+2 @@ -3082,7 +3082,7 @@ break; default: - *prangeMax = (m_SndFile.m_nType & MOD_TYPE_XM) ? 15 : 9; + *prangeMax = (m_SndFile.GetType() & MOD_TYPE_XM) ? 15 : 9; } } return (gVolCmdInfo[ndx].dwFormats & m_SndFile.m_nType) ? TRUE : FALSE; @@ -3166,6 +3166,7 @@ } + enmParameteredMacroType CModDoc::GetMacroType(CString value) //---------------------------------------------------------- { Modified: trunk/OpenMPT/soundlib/modcommand.cpp =================================================================== --- trunk/OpenMPT/soundlib/modcommand.cpp 2011-04-05 13:03:17 UTC (rev 841) +++ trunk/OpenMPT/soundlib/modcommand.cpp 2011-04-08 22:23:19 UTC (rev 842) @@ -51,10 +51,10 @@ 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; + case 0x70: m->command = CMD_NONE; // No NNA / envelope control in MOD/XM format // rest are the same } } @@ -106,8 +106,18 @@ { if(m->IsPcNote()) { + MODCOMMAND::COMMAND newcommand = (m->note == NOTE_PC) ? CMD_MIDI : CMD_SMOOTHMIDI; + if(!GetModSpecifications(nNewType).HasCommand(newcommand)) + { + newcommand = CMD_MIDI; // assuming that this was CMD_SMOOTHMIDI + } + if(!GetModSpecifications(nNewType).HasCommand(newcommand)) + { + newcommand = CMD_NONE; + } + 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->command = newcommand; // might be removed later m->volcmd = VOLCMD_NONE; m->note = NOTE_NONE; m->instr = 0; @@ -298,11 +308,21 @@ switch(m->command) { case CMD_S3MCMDEX: - if(m->param == 0x91) + switch(m->param & 0xF0) { - // surround remap (this is the "official" command) - m->command = CMD_PANNING8; - m->param = 0xA4; + case 0x70: m->command = CMD_NONE; break; // No NNA / envelope control in S3M format + case 0x90: + if(m->param == 0x91) + { + // surround remap (this is the "official" command) + m->command = CMD_PANNING8; + m->param = 0xA4; + } else if(m->param == 0x90) + { + m->command = CMD_PANNING8; + m->param = 0x40; + } + break; } break; case CMD_SMOOTHMIDI: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-08 22:25:14
|
Revision: 843 http://modplug.svn.sourceforge.net/modplug/?rev=843&view=rev Author: saga-games Date: 2011-04-08 22:25:07 +0000 (Fri, 08 Apr 2011) Log Message: ----------- [Fix] J2B Loader: Empty sample slots are now treated correct in new J2B (AM) files). [Fix] DMF Loader: Many many improvements to portamento, pattersn with variable number of tracks and other effects. [Mod] OpenMPT: Version is now 1.19.01.01 Modified Paths: -------------- trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/load_j2b.cpp Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2011-04-08 22:23:19 UTC (rev 842) +++ trunk/OpenMPT/mptrack/version.h 2011-04-08 22:25:07 UTC (rev 843) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 19 #define VER_MINOR 01 -#define VER_MINORMINOR 00 +#define VER_MINORMINOR 01 //Creates version number from version parts that appears in version string. //For example MAKE_VERSION_NUMERIC(1,17,02,28) gives version number of Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-08 22:23:19 UTC (rev 842) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-08 22:25:07 UTC (rev 843) @@ -12,6 +12,9 @@ /////////////////////////////////////////////////////// #include "stdafx.h" #include "Loaders.h" +#ifdef MODPLUG_TRACKER +#include "../mptrack/Moddoc.h" +#endif // MODPLUG_TRACKER //#define DMFLOG @@ -86,6 +89,16 @@ #endif +// Convert portamento value (not very accurate, to say the least) +uint8 DMFporta2MPT(uint8 val) +//--------------------------- +{ + if(val <= 0x0F) + return (val | 0xF0); + else + return (val / 4); +} + bool CSoundFile::ReadDMF(const BYTE *lpStream, const DWORD dwMemLength) //--------------------------------------------------------------------- { @@ -102,10 +115,25 @@ memcpy(m_szNames[0], pfh->songname, 30); SpaceToNullStringFixed<30>(m_szNames[0]); m_nType = MOD_TYPE_DMF; + m_dwSongFlags = SONG_LINEARSLIDES | SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS; m_nChannels = 0; #ifdef DMFLOG Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength); #endif + +#ifdef MODPLUG_TRACKER + if(GetpModDoc() != nullptr) + { + FileHistory mptHistory; + MemsetZero(mptHistory); + mptHistory.loadDate.tm_mday = CLAMP(pfh->date[0], 0, 31); + mptHistory.loadDate.tm_mon = CLAMP(pfh->date[1], 1, 12) - 1; + mptHistory.loadDate.tm_year = pfh->date[2]; + GetpModDoc()->GetFileHistory()->clear(); + GetpModDoc()->GetFileHistory()->push_back(mptHistory); + } +#endif // MODPLUG_TRACKER + while (dwMemPos + 7 < dwMemLength) { DWORD id = *((LPDWORD)(lpStream+dwMemPos)); @@ -135,7 +163,7 @@ if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1; Order.resize(nseq, Order.GetInvalidPatIndex()); if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart; - for (UINT i = 0; i < nseq; i++) Order[i] = (PATTERNINDEX)sequ->sequ[i]; + for (UINT i = 0; i < nseq - 2; i++) Order[i] = (PATTERNINDEX)sequ->sequ[i]; } dwMemPos += sequ->seqsize + 8; break; @@ -150,10 +178,12 @@ if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit; numpat = patt->numpat; if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS; + m_nChannels = patt->tracks; if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo; if (m_nChannels > 32) m_nChannels = 32; if (m_nChannels < 1) m_nChannels = 1; + for (UINT npat=0; npat<numpat; npat++) { DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos); @@ -163,13 +193,19 @@ UINT tracks = pt->tracks; if (tracks > 32) tracks = 32; UINT ticks = pt->ticks; - if (ticks > 256) ticks = 256; - if (ticks < 16) ticks = 16; + if (ticks > MAX_PATTERN_ROWS) ticks = MAX_PATTERN_ROWS; + if (ticks < 1) ticks = 1; dwPos += 8; if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; if(Patterns.Insert(npat, ticks)) goto dmfexit; MODCOMMAND *m = Patterns[npat]; + // If pattern "width" changes, leftover voices are killed: + for(CHANNELINDEX nChn = tracks; nChn < m_nChannels; nChn++) + { + m[nChn].note = NOTE_NOTECUT; + } + DWORD d = dwPos; dwPos += pt->jmpsize; UINT ttype = 1; @@ -217,8 +253,17 @@ if (info & 0x20) { cmd.note = lpStream[d++]; - if ((cmd.note) && (cmd.note < 0xfe)) cmd.note &= 0x7f; - if ((cmd.note) && (cmd.note < 128)) cmd.note += 24; + if (cmd.note >= 1 && cmd.note <= 108) + { + cmd.note += 24; + } else if (cmd.note >= 129 && cmd.note <= 236) + { + // "ghost notes" for portamento that are actually not played... how the hell should we treat them?! + cmd.note += 24; + } else if (cmd.note == 255) + { + cmd.note = NOTE_NOTECUT; + } } // Volume if (info & 0x10) @@ -226,7 +271,7 @@ cmd.volcmd = VOLCMD_VOLUME; cmd.vol = (lpStream[d++]+3)>>2; } - // Effect 1 + // Effect 1 - Instrument if (info & 0x08) { BYTE efx = lpStream[d++]; @@ -234,20 +279,23 @@ switch(efx) { // 1: Key Off - case 1: if (!cmd.note) cmd.note = 0xFE; break; - // 2: Set Loop - // 4: Sample Delay + case 1: if (!cmd.note) cmd.note = NOTE_NOTECUT; break; + // 2: Stop Sample Loop + case 2: if (!cmd.note) cmd.note = NOTE_KEYOFF; break; + // 4: Sample Delay, in 1/256th rows case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 5: Retrig + // 5: Retrig, in 1/256th rows case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break; // 6: Offset case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break; + // 10: Tekkno Invert + case 10: cmd.command = CMD_S3MCMDEX; cmd.param = 0x9F; break; #ifdef DMFLOG default: Log("FX1: %02X.%02X\n", efx, eval); #endif } } - // Effect 2 + // Effect 2 - Note if (info & 0x04) { BYTE efx = lpStream[d++]; @@ -261,22 +309,22 @@ // 3: Arpeggio case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break; // 4: Portamento Up - case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; + case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = DMFporta2MPT(eval); break; // 5: Portamento Down - case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = (eval >= 0xe0) ? 0xdf : eval; break; + case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = DMFporta2MPT(eval); break; // 6: Tone Portamento - case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = eval; break; + case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = DMFporta2MPT(eval); break; // 8: Vibrato case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break; - // 12: Note cut + // 12: Note cut, in 1/256th rows case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; } - else if (!cmd.note) { cmd.note = 0xfe; } break; + else if (!cmd.note) { cmd.note = NOTE_NOTECUT; } break; #ifdef DMFLOG default: Log("FX2: %02X.%02X\n", efx, eval); #endif } } - // Effect 3 + // Effect 3 - Volume if (info & 0x02) { BYTE efx = lpStream[d++]; @@ -296,7 +344,7 @@ else { cmd.command = CMD_PANNING8; cmd.param = eval; } break; // 8: Pan Slide Left case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval<<4; break; + cmd.command = CMD_PANNINGSLIDE; cmd.param = eval << 4; break; // 9: Pan Slide Right case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break; @@ -305,6 +353,21 @@ #endif } } + + // Note without instrument == just reset pitch, do not retrigger + if(cmd.instr == 0 && cmd.note != NOTE_NONE && NOTE_IS_VALID(cmd.note) && cmd.command != CMD_TONEPORTAMENTO) + { + if(cmd.volcmd == VOLCMD_NONE) + { + cmd.volcmd = VOLCMD_TONEPORTAMENTO; + cmd.vol = 9; + } else + { + cmd.command = CMD_TONEPORTAMENTO; + cmd.param = 0xFF; + } + } + // Store effect if (i < m_nChannels) p[i] = cmd; if (d > dwPos) @@ -389,14 +452,14 @@ DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); MODSAMPLE *psmp = &Samples[iSmp]; psmp->nLength = psh->len; - psmp->nLoopStart = psh->loopstart; - psmp->nLoopEnd = psh->loopend; + psmp->nSustainStart = psh->loopstart; + psmp->nSustainEnd = psh->loopend; psmp->nC5Speed = psh->c3speed; psmp->nGlobalVol = 64; psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256; psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0; if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1; - if (psh->flags & 1) psmp->uFlags |= CHN_LOOP; + if (psh->flags & 1) psmp->uFlags |= CHN_SUSTAINLOOP; smplflags[iSmp] = psh->flags; dwPos += (pfh->version < 8) ? 22 : 30; #ifdef DMFLOG Modified: trunk/OpenMPT/soundlib/load_j2b.cpp =================================================================== --- trunk/OpenMPT/soundlib/load_j2b.cpp 2011-04-08 22:23:19 UTC (rev 842) +++ trunk/OpenMPT/soundlib/load_j2b.cpp 2011-04-08 22:25:07 UTC (rev 843) @@ -35,6 +35,9 @@ #define AMCHUNKID_AI__ 0x20204941 #define AMCHUNKID_AS__ 0x20205341 +// Header flags +#define AMHEAD_LINEAR 0x01 + // Envelope flags #define AMENV_ENABLED 0x01 #define AMENV_SUSTAIN 0x02 @@ -78,7 +81,7 @@ uint8 channels; uint8 speed; uint8 tempo; - uint32 unknown; // 0x16078035 if original file was MOD, 0xC50100FF for everything else? + uint32 unknown; // 0x16078035 if original file was MOD, 0xC50100FF for everything else? it's 0xFF00FFFF in Carrotus.j2b (AMFF version) uint8 globalvolume; }; @@ -489,7 +492,7 @@ memcpy(m_szNames[0], mainchunk->songname, 32); SpaceToNullStringFixed<31>(m_szNames[0]); m_dwSongFlags = SONG_ITOLDEFFECTS | SONG_ITCOMPATGXX; - if(!(mainchunk->flags & 0x01)) m_dwSongFlags |= SONG_LINEARSLIDES; + if(!(mainchunk->flags & AMHEAD_LINEAR)) m_dwSongFlags |= SONG_LINEARSLIDES; if(mainchunk->channels < 1) return false; m_nChannels = min(mainchunk->channels, MAX_BASECHANNELS); m_nDefaultSpeed = mainchunk->speed; @@ -497,7 +500,7 @@ m_nDefaultGlobalVolume = mainchunk->globalvolume << 1; m_nSamplePreAmp = m_nVSTiVolume = 48; m_nType = MOD_TYPE_J2B; - ASSERT(LittleEndian(mainchunk->unknown) == 0xFF0001C5 || LittleEndian(mainchunk->unknown) == 0x35800716); + ASSERT(LittleEndian(mainchunk->unknown) == 0xFF0001C5 || LittleEndian(mainchunk->unknown) == 0x35800716 || LittleEndian(mainchunk->unknown) == 0xFF00FFFF); // It seems like there's no way to differentiate between // Muted and Surround channels (they're all 0xA0) - might @@ -688,6 +691,11 @@ const size_t nTotalSmps = LittleEndianW(instheader->numsamples); + if(nTotalSmps == 0) + { + MemsetZero(pIns->Keyboard); + } + DWORD dwChunkPos; // read sample sub-chunks (RIFF nesting ftw) @@ -705,15 +713,16 @@ if(LittleEndian(*(uint32 *)(lpStream + dwChunkPos)) != AMCHUNKID_AS__) break; dwChunkPos += 4; + // Moved this stuff here (was below the next ASSERT_CAN_READ_CHUNK) because of instrument 12 in Carrotus.j2b + if(m_nSamples + 1 >= MAX_SAMPLES) + break; + const SAMPLEINDEX nSmp = ++m_nSamples; + ASSERT_CAN_READ_CHUNK(sizeof(AMCHUNK_SAMPLE)); const AMCHUNK_SAMPLE *smpchunk = (AMCHUNK_SAMPLE *)(lpStream + dwChunkPos); if(smpchunk->signature != AMCHUNKID_SAMP) break; // SAMP - if(m_nSamples + 1 >= MAX_SAMPLES) - break; - const SAMPLEINDEX nSmp = ++m_nSamples; - MemsetZero(Samples[nSmp]); memcpy(m_szNames[nSmp], smpchunk->name, 32); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-09 17:16:50
|
Revision: 844 http://modplug.svn.sourceforge.net/modplug/?rev=844&view=rev Author: saga-games Date: 2011-04-09 17:16:43 +0000 (Sat, 09 Apr 2011) Log Message: ----------- [Imp] DMF Loader: Some more small improvements (fake support for vibrato / tremolo / tremor) [Fix] VST Editor: Fixed note handling with plugins that actually don't support MIDI input (http://bugs.openmpt.org/view.php?id=102) [Fix] Mod Conversion: Sustain loop conversion was all wrong + some minor fixes Modified Paths: -------------- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/soundlib/LOAD_DMF.CPP trunk/OpenMPT/soundlib/Snd_defs.h Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.cpp =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-04-08 22:25:07 UTC (rev 843) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-04-09 17:16:43 UTC (rev 844) @@ -383,7 +383,9 @@ } } else { - return true; + // used to return true but that doesn't make sense to me. + // if this is true, random (sample) channels will be retriggered when pressing notes in the editor... + return false; } } Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2011-04-08 22:25:07 UTC (rev 843) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2011-04-09 17:16:43 UTC (rev 844) @@ -53,7 +53,7 @@ // shorten instrument envelope if necessary (for mod conversion) const UINT iEnvMax = pSndFile->GetModSpecifications().envelopePointsMax; - #define TRIMENV(nPat) if(nPat > iEnvMax) { nPat = iEnvMax; CHANGEMODTYPE_WARNING(wTrimmedEnvelopes); } + #define TRIMENV(iEnvLen) if(iEnvLen > iEnvMax) { iEnvLen = iEnvMax; CHANGEMODTYPE_WARNING(wTrimmedEnvelopes); } TRIMENV(mptEnv->nNodes); TRIMENV(mptEnv->nLoopStart); @@ -62,9 +62,11 @@ TRIMENV(mptEnv->nSustainEnd); if(mptEnv->nReleaseNode != ENV_RELEASE_NODE_UNSET) { - TRIMENV(mptEnv->nReleaseNode); - if(!pSndFile->GetModSpecifications().hasReleaseNode) + if(pSndFile->GetModSpecifications().hasReleaseNode) { + TRIMENV(mptEnv->nReleaseNode); + } else + { mptEnv->nReleaseNode = ENV_RELEASE_NODE_UNSET; CHANGEMODTYPE_WARNING(wReleaseNode); } @@ -117,7 +119,7 @@ nResizedPatterns++; } - if(((m_SndFile.m_nInstruments) || (nResizedPatterns)) && (nNewType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) + if((m_SndFile.GetNumInstruments() || nResizedPatterns) && (nNewType & (MOD_TYPE_MOD|MOD_TYPE_S3M))) { if(::MessageBox(NULL, "This operation will convert all instruments to samples,\n" @@ -145,7 +147,7 @@ CHANGEMODTYPE_WARNING(wResizedPatterns); } - // Removing all instrument headers + // Removing all instrument headers from channels for(CHANNELINDEX nChn = 0; nChn < MAX_CHANNELS; nChn++) { m_SndFile.Chn[nChn].pModInstrument = nullptr; @@ -253,8 +255,14 @@ // Do some sample conversion - for(SAMPLEINDEX nSmp = 1; nSmp <= m_SndFile.m_nSamples; nSmp++) + for(SAMPLEINDEX nSmp = 1; nSmp <= m_SndFile.GetNumSamples(); nSmp++) { + // Too many samples? Only 31 samples allowed in MOD format... + if(newTypeIsMOD && nSmp > 31 && m_SndFile.Samples[nSmp].nLength > 0) + { + CHANGEMODTYPE_WARNING(wMOD31Samples); + } + // No Bidi / Sustain loops / Autovibrato for MOD/S3M if(newTypeIsMOD || newTypeIsS3M) { @@ -265,20 +273,17 @@ CHANGEMODTYPE_WARNING(wSampleBidiLoops); } - // Sustain loops - if(m_SndFile.Samples[nSmp].nSustainStart || m_SndFile.Samples[nSmp].nSustainEnd) + // Sustain loops - convert to normal loops + if((m_SndFile.Samples[nSmp].uFlags & CHN_SUSTAINLOOP) != 0) { - // We can at least try to convert sustain loops to normal loops - if(m_SndFile.Samples[nSmp].nLoopEnd == 0) - { - m_SndFile.Samples[nSmp].nSustainStart = m_SndFile.Samples[nSmp].nLoopStart; - m_SndFile.Samples[nSmp].nSustainEnd = m_SndFile.Samples[nSmp].nLoopEnd; - m_SndFile.Samples[nSmp].uFlags |= CHN_LOOP; - } - m_SndFile.Samples[nSmp].nSustainStart = m_SndFile.Samples[nSmp].nSustainEnd = 0; - m_SndFile.Samples[nSmp].uFlags &= ~(CHN_SUSTAINLOOP|CHN_PINGPONGSUSTAIN); + // We probably overwrite a normal loop here, but since sustain loops are evaluated before normal loops, this is just correct. + m_SndFile.Samples[nSmp].nLoopStart = m_SndFile.Samples[nSmp].nSustainStart; + m_SndFile.Samples[nSmp].nLoopEnd = m_SndFile.Samples[nSmp].nSustainEnd; + m_SndFile.Samples[nSmp].uFlags |= CHN_LOOP; CHANGEMODTYPE_WARNING(wSampleSustainLoops); } + m_SndFile.Samples[nSmp].nSustainStart = m_SndFile.Samples[nSmp].nSustainEnd = 0; + m_SndFile.Samples[nSmp].uFlags &= ~(CHN_SUSTAINLOOP|CHN_PINGPONGSUSTAIN); // Autovibrato if(m_SndFile.Samples[nSmp].nVibDepth || m_SndFile.Samples[nSmp].nVibRate || m_SndFile.Samples[nSmp].nVibSweep) @@ -323,10 +328,10 @@ } } - // Convert IT/MPT to XM (instruments) - if(oldTypeIsIT_MPT && newTypeIsXM) + for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.GetNumInstruments(); nIns++) { - for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.GetNumInstruments(); nIns++) + // Convert IT/MPT to XM (fix instruments) + if(oldTypeIsIT_MPT && newTypeIsXM) { MODINSTRUMENT *pIns = m_SndFile.Instruments[nIns]; if (pIns) @@ -358,12 +363,8 @@ pIns->nIFR &= 0x7F; } } - } - - // Instrument tunings - if(oldTypeIsMPT) - { - for(INSTRUMENTINDEX nIns = 1; nIns <= m_SndFile.GetNumInstruments(); nIns++) + // Convert MPT to anything - remove instrument tunings + if(oldTypeIsMPT) { if(m_SndFile.Instruments[nIns] != nullptr && m_SndFile.Instruments[nIns]->pTuning != nullptr) { @@ -382,12 +383,6 @@ m_SndFile.m_nSamplePreAmp = 48; m_SndFile.m_nVSTiVolume = 48; CHANGEMODTYPE_WARNING(wMODGlobalVars); - - // Too many samples? - if(m_SndFile.m_nSamples > 31) - { - CHANGEMODTYPE_WARNING(wMOD31Samples); - } } // Is the "restart position" value allowed in this format? Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-08 22:25:07 UTC (rev 843) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-09 17:16:43 UTC (rev 844) @@ -213,10 +213,10 @@ UINT glbinfobyte = 0; UINT pbeat = (pt->beat & 0xf0) ? pt->beat>>4 : 8; BOOL tempochange = (pt->beat & 0xf0) ? TRUE : FALSE; - memset(infobyte, 0, sizeof(infobyte)); + MemsetZero(infobyte); for (UINT row=0; row<ticks; row++) { - MODCOMMAND *p = &m[row*m_nChannels]; + MODCOMMAND *p = &m[row * m_nChannels]; // Parse track global effects if (!glbinfobyte) { @@ -259,7 +259,7 @@ } else if (cmd.note >= 129 && cmd.note <= 236) { // "ghost notes" for portamento that are actually not played... how the hell should we treat them?! - cmd.note += 24; + cmd.note = (cmd.note & 0x7F) + 24; } else if (cmd.note == 255) { cmd.note = NOTE_NOTECUT; @@ -314,8 +314,15 @@ case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = DMFporta2MPT(eval); break; // 6: Tone Portamento case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = DMFporta2MPT(eval); break; - // 8: Vibrato - case 8: cmd.command = CMD_VIBRATO; cmd.param = eval; break; + // 8: Vibrato Sine + // 9: Vibrato Triangle + // 10: Vibrato Square + case 8: + case 9: + case 10: + cmd.command = CMD_VIBRATO; + cmd.param = (0xF0 - (eval & 0xF0)) | ((eval & 0x0F) / 2); + break; // 12: Note cut, in 1/256th rows case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; } else if (!cmd.note) { cmd.note = NOTE_NOTECUT; } break; @@ -339,6 +346,19 @@ case 2: if (eval == 0xff) break; eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; cmd.command = CMD_VOLUMESLIDE; cmd.param = eval; break; + // 3: Tremor + case 3: + cmd.command = CMD_TREMOR; cmd.param = eval; + break; + // 4: Tremolo Sine + // 5: Tremolo Triangle + // 6: Tremolo Square + case 4: + case 5: + case 6: + cmd.command = CMD_TREMOLO; + cmd.param = (0xF0 - (eval & 0xF0)) | ((eval & 0x0F) / 2); + break; // 7: Set Pan case 7: if (!cmd.volcmd) { cmd.volcmd = VOLCMD_PANNING; cmd.vol = (eval+3)>>2; } else { cmd.command = CMD_PANNING8; cmd.param = eval; } break; @@ -627,7 +647,7 @@ UINT actnode; BYTE value, sign, delta = 0; - memset(&tree, 0, sizeof(tree)); + MemsetZero(tree); tree.ibuf = ibuf; tree.ibufmax = ibufmax; DMFNewNode(&tree); Modified: trunk/OpenMPT/soundlib/Snd_defs.h =================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h 2011-04-08 22:25:07 UTC (rev 843) +++ trunk/OpenMPT/soundlib/Snd_defs.h 2011-04-09 17:16:43 UTC (rev 844) @@ -375,6 +375,7 @@ // Release node defines #define ENV_RELEASE_NODE_UNSET 0xFF #define NOT_YET_RELEASED (-1) +STATIC_ASSERT(ENV_RELEASE_NODE_UNSET > MAX_ENVPOINTS); enum { @@ -411,8 +412,8 @@ // MIDI Macros #define MACRO_MASK 0x7F5F7F5F -#define MACRO_INTERNAL 0x30463046 // internal macro, low 7 bits (f.e. cutoff, resonance, low plugin params) -#define MACRO_INTERNALEX 0x31463046 // internal macro, high 7 bits (high plugin params) +#define MACRO_INTERNAL 0x30463046 // internal macro (F0F0), controls lower 8 bits (f.e. cutoff, resonance, low plugin params) +#define MACRO_INTERNALEX 0x31463046 // internal extended macro (F0F1), controls higher 8 bits (high plugin params) // Vibrato Types #define VIB_SINE 0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-11 16:44:14
|
Revision: 845 http://modplug.svn.sourceforge.net/modplug/?rev=845&view=rev Author: saga-games Date: 2011-04-11 16:44:07 +0000 (Mon, 11 Apr 2011) Log Message: ----------- [Ref] TryWriteEffect can now also try to write an effect on a previous row if there's no space left on the current row [Fix] MPT hack detector: It was possible that the log said "no hacks found" if only invalid pattern commands were found. [Fix] IT Compatibility: Panning slides with both parameter nibbles set were not ignored. Modified Paths: -------------- trunk/OpenMPT/mptrack/MPTHacks.cpp trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/soundlib/Load_psm.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/modcommand.cpp Modified: trunk/OpenMPT/mptrack/MPTHacks.cpp =================================================================== --- trunk/OpenMPT/mptrack/MPTHacks.cpp 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/mptrack/MPTHacks.cpp 2011-04-11 16:44:07 UTC (rev 845) @@ -157,7 +157,10 @@ foundHere = false; m_SndFile.Patterns.ForEachModCommand(FixHackedPatterns(originalSpecs, m_SndFile.GetType(), autofix, &foundHere)); if(foundHere) + { AddToLog("Found invalid pattern commands\n"); + foundHacks = true; + } // Check for pattern names foundHere = false; Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2011-04-11 16:44:07 UTC (rev 845) @@ -141,7 +141,7 @@ // try to save short patterns by inserting a pattern break. if(m_SndFile.Patterns[nPat].GetNumRows() < 64) { - m_SndFile.TryWriteEffect(nPat, m_SndFile.Patterns[nPat].GetNumRows() - 1, CMD_PATTERNBREAK, 0, false, CHANNELINDEX_INVALID, false, true); + m_SndFile.TryWriteEffect(nPat, m_SndFile.Patterns[nPat].GetNumRows() - 1, CMD_PATTERNBREAK, 0, false, CHANNELINDEX_INVALID, false, weTryNextRow); } m_SndFile.Patterns[nPat].Resize(64, false); CHANGEMODTYPE_WARNING(wResizedPatterns); @@ -246,7 +246,7 @@ } if(addBreak) { - m_SndFile.TryWriteEffect(nPat, m_SndFile.Patterns[nPat].GetNumRows() - 1, CMD_PATTERNBREAK, 0, false, CHANNELINDEX_INVALID, false, false); + m_SndFile.TryWriteEffect(nPat, m_SndFile.Patterns[nPat].GetNumRows() - 1, CMD_PATTERNBREAK, 0, false, CHANNELINDEX_INVALID, false, weIgnore); } } Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2011-04-11 16:44:07 UTC (rev 845) @@ -1282,7 +1282,7 @@ GetLengthType length = m_SndFile.GetLength(eNoAdjust); if(length.endOrder != ORDERINDEX_INVALID && length.endRow != ROWINDEX_INVALID) { - result = m_SndFile.TryWriteEffect(m_SndFile.Order[length.endOrder], length.endRow, CMD_POSITIONJUMP, m_SndFile.m_nRestartPos, false, CHANNELINDEX_INVALID, false, true); + result = m_SndFile.TryWriteEffect(m_SndFile.Order[length.endOrder], length.endRow, CMD_POSITIONJUMP, m_SndFile.m_nRestartPos, false, CHANNELINDEX_INVALID, false, weTryNextRow); } m_SndFile.m_nRestartPos = 0; return result; Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2011-04-11 16:44:07 UTC (rev 845) @@ -775,14 +775,14 @@ for(CHANNELINDEX nChn = 0; nChn < m_nChannels; nChn++) { if(subsongs[i].channelSurround[nChn] == true) - TryWriteEffect(startPattern, 0, CMD_S3MCMDEX, 0x91, false, nChn, false, true); + TryWriteEffect(startPattern, 0, CMD_S3MCMDEX, 0x91, false, nChn, false, weTryNextRow); else - TryWriteEffect(startPattern, 0, CMD_PANNING8, subsongs[i].channelPanning[nChn], false, nChn, false, true); + TryWriteEffect(startPattern, 0, CMD_PANNING8, subsongs[i].channelPanning[nChn], false, nChn, false, weTryNextRow); } } // write default tempo/speed to pattern - TryWriteEffect(startPattern, 0, CMD_SPEED, subsongs[i].defaultSpeed, false, CHANNELINDEX_INVALID, false, true); - TryWriteEffect(startPattern, 0, CMD_TEMPO, subsongs[i].defaultTempo, false, CHANNELINDEX_INVALID, false, true); + TryWriteEffect(startPattern, 0, CMD_SPEED, subsongs[i].defaultSpeed, false, CHANNELINDEX_INVALID, false, weTryNextRow); + TryWriteEffect(startPattern, 0, CMD_TEMPO, subsongs[i].defaultTempo, false, CHANNELINDEX_INVALID, false, weTryNextRow); // don't write channel volume for now, as it's always set to 100% anyway @@ -800,7 +800,7 @@ break; } } - TryWriteEffect(endPattern, lastRow, CMD_POSITIONJUMP, (BYTE)subsongs[i].restartPos, false, CHANNELINDEX_INVALID, false, true); + TryWriteEffect(endPattern, lastRow, CMD_POSITIONJUMP, (BYTE)subsongs[i].restartPos, false, CHANNELINDEX_INVALID, false, weTryNextRow); } } } @@ -1194,7 +1194,7 @@ } // Pattern break for short patterns (so saving the modules as S3M won't break it) if(phdr->numRows != 64) - TryWriteEffect(nPat, phdr->numRows - 1, CMD_PATTERNBREAK, 0, false, CHANNELINDEX_INVALID, false, false); + TryWriteEffect(nPat, phdr->numRows - 1, CMD_PATTERNBREAK, 0, false, CHANNELINDEX_INVALID, false, weTryNextRow); dwMemPos = dwNextPattern; if(dwMemPos > dwPatEndPos) break; Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-04-11 16:44:07 UTC (rev 845) @@ -2643,8 +2643,15 @@ { if (!(m_dwSongFlags & SONG_FIRSTTICK)) { - if (param & 0x0F) nPanSlide = (int)((param & 0x0F) << 2); - else nPanSlide = -(int)((param & 0xF0) >> 2); + if (param & 0x0F) + { + if(!IsCompatibleMode(TRK_IMPULSETRACKER) || (param & 0xF0) == 0) + nPanSlide = (int)((param & 0x0F) << 2); + } else + { + if(!IsCompatibleMode(TRK_IMPULSETRACKER) || (param & 0x0F) == 0) + nPanSlide = -(int)((param & 0xF0) >> 2); + } } } } else @@ -2654,13 +2661,11 @@ // IT compatibility: Ignore slide commands with both nibbles set. if (param & 0x0F) { - if(!IsCompatibleMode(TRK_IMPULSETRACKER) || (param & 0xF0) == 0) - nPanSlide = -(int)((param & 0x0F) << 2); + nPanSlide = -(int)((param & 0x0F) << 2); } else { - if(!IsCompatibleMode(TRK_IMPULSETRACKER) || (param & 0x0F) == 0) - nPanSlide = (int)((param & 0xF0) >> 2); + nPanSlide = (int)((param & 0xF0) >> 2); } // XM compatibility: FT2's panning slide is not as deep if(IsCompatibleMode(TRK_FASTTRACKER2)) @@ -3157,7 +3162,7 @@ pChn->m_nPlugParamValueStep = (float)((int)dwParam - pChn->m_nPlugInitialParamValue) / (float)m_nMusicSpeed; } //update param on all ticks - pChn->nCutOff = (BYTE) (pChn->m_nPlugInitialParamValue + (m_nTickCount + 1 ) *pChn->m_nPlugParamValueStep + 0.5); + pChn->nCutOff = (BYTE) (pChn->m_nPlugInitialParamValue + (m_nTickCount + 1) * pChn->m_nPlugParamValueStep + 0.5); } pChn->nRestoreCutoffOnNewNote = 0; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-11 16:44:07 UTC (rev 845) @@ -511,6 +511,15 @@ }; +// Row advance mode for TryWriteEffect() +enum writeEffectAllowRowChange +{ + weIgnore, // If effect can't be written, abort. + weTryNextRow, // If effect can't be written, try next row. + weTryPreviousRow, // If effect can't be written, try previous row. +}; + + //Note: These are bit indeces. MSF <-> Mod(Specific)Flag. //If changing these, ChangeModTypeTo() might need modification. const BYTE MSF_COMPATIBLE_PLAY = 0; //IT/MPT/XM @@ -922,7 +931,7 @@ UINT GetNumTicksOnCurrentRow() { return m_nMusicSpeed * (m_nPatternDelay + 1) + m_nFrameDelay; }; 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); + bool TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn = CHANNELINDEX_INVALID, bool bAllowMultipleEffects = true, writeEffectAllowRowChange allowRowChange = weIgnore, bool bRetry = true); // Read/Write sample functions char GetDeltaValue(char prev, UINT n) const { return (char)(prev + CompressionTable[n & 0x0F]); } Modified: trunk/OpenMPT/soundlib/modcommand.cpp =================================================================== --- trunk/OpenMPT/soundlib/modcommand.cpp 2011-04-09 17:16:43 UTC (rev 844) +++ trunk/OpenMPT/soundlib/modcommand.cpp 2011-04-11 16:44:07 UTC (rev 845) @@ -674,12 +674,12 @@ 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 + allowRowChange - Indicates whether it is allowed to use the next or previous 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) NOTE: Effect remapping is only implemented for a few basic effects. */ -bool CSoundFile::TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn, bool bAllowMultipleEffects, bool bAllowNextRow, bool bRetry) -//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +bool CSoundFile::TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn, bool bAllowMultipleEffects, writeEffectAllowRowChange allowRowChange, bool bRetry) +//---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- { // First, reject invalid parameters. if(!Patterns.IsValidIndex(nPat) || nRow >= Patterns[nPat].GetNumRows() || (nChn >= GetNumChannels() && nChn != CHANNELINDEX_INVALID)) @@ -810,14 +810,17 @@ } if(nNewEffect != CMD_NONE) { - if(TryWriteEffect(nPat, nRow, nNewEffect, nParam, !bIsVolumeEffect, nChn, bAllowMultipleEffects, bAllowNextRow, false) == true) return true; + if(TryWriteEffect(nPat, nRow, nNewEffect, nParam, !bIsVolumeEffect, nChn, bAllowMultipleEffects, allowRowChange, 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())) + if(allowRowChange == weTryNextRow && (nRow + 1 < Patterns[nPat].GetNumRows())) { - return TryWriteEffect(nPat, nRow + 1, nEffect, nParam, bIsVolumeEffect, nChn, bAllowMultipleEffects, bAllowNextRow, bRetry); + return TryWriteEffect(nPat, nRow + 1, nEffect, nParam, bIsVolumeEffect, nChn, bAllowMultipleEffects, allowRowChange, bRetry); + } else if(allowRowChange == weTryPreviousRow && (nRow > 0)) + { + return TryWriteEffect(nPat, nRow - 1, nEffect, nParam, bIsVolumeEffect, nChn, bAllowMultipleEffects, allowRowChange, bRetry); } return false; @@ -859,7 +862,7 @@ { // hack for people who can't type F twice :) *e = VOLCMD_TONEPORTAMENTO; - *p = 0xFF; + *p = 9; return true; } for (uint8 n = 0; n < 10; n++) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-11 19:50:27
|
Revision: 846 http://modplug.svn.sourceforge.net/modplug/?rev=846&view=rev Author: saga-games Date: 2011-04-11 19:50:20 +0000 (Mon, 11 Apr 2011) Log Message: ----------- [Imp] Rewrote DMF loader completely for higher accuracy. [Mod] OpenMPT: Version is now 1.19.01.02 Modified Paths: -------------- trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/soundlib/LOAD_DMF.CPP Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2011-04-11 16:44:07 UTC (rev 845) +++ trunk/OpenMPT/mptrack/version.h 2011-04-11 19:50:20 UTC (rev 846) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 19 #define VER_MINOR 01 -#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_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-11 16:44:07 UTC (rev 845) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-11 19:50:20 UTC (rev 846) @@ -1,589 +1,1046 @@ /* - * This source code is public domain. + * load_dmf.cpp + * ------------ + * Purpose: Load DMF modules (X-Tracker by D-LUSiON). + * Notes : If it wasn't already outdated when the tracker was released, this would be a rather interesting + * and in some parts even sophisticated format - effect columns are separated by effect type, an easy to + * understand BPM tempo mode, effect durations are always divided into a 256th row, vibrato effects are + * specified by period length and the same 8-Bit granularity is used for both volume and panning. + * Unluckily, this format does not offer any envelopes or multi-sample instruments, and bidi sample loops + * are missing as well, so it was already well behind FT2 and IT back then. + * Authors: Johannes Schultz (mostly based on DMF.TXT, DMF_EFFC.TXT, trial and error and some invaluable hints by Zatzen) * - * Copied to OpenMPT from libmodplug. - * - * Authors: Olivier Lapicque <oli...@jp...> - * OpenMPT dev(s) (miscellaneous modifications) -*/ + */ -/////////////////////////////////////////////////////// -// DMF DELUSION DIGITAL MUSIC FILEFORMAT (X-Tracker) // -/////////////////////////////////////////////////////// + #include "stdafx.h" #include "Loaders.h" #ifdef MODPLUG_TRACKER #include "../mptrack/Moddoc.h" #endif // MODPLUG_TRACKER -//#define DMFLOG +// 32-bit chunk identifiers +#define DMF_DDMF 0x464D4444 +#define DMF_CMSG 0x47534D43 +#define DMF_SEQU 0x55514553 +#define DMF_PATT 0x54544150 +#define DMF_SMPI 0x49504D53 +#define DMF_SMPD 0x44504D53 +#define DMF_SMPJ 0x4A504D53 +#define DMF_ENDE 0x45444E45 -#pragma warning(disable:4244) //"conversion from 'type1' to 'type2', possible loss of data" +// Pattern flags - global track +#define DMFPAT_GLOBPACK 0x80 // Pack information for global track follows +#define DMFPAT_GLOBMASK 0x3F // Mask for global effects +// Pattern flags - note tracks +#define DMFPAT_COUNTER 0x80 // Pack information for current channel follows +#define DMFPAT_INSTR 0x40 // Instrument number present +#define DMFPAT_NOTE 0x20 // Note present +#define DMFPAT_VOLUME 0x10 // Volume present +#define DMFPAT_INSEFF 0x08 // Instrument effect present +#define DMFPAT_NOTEEFF 0x04 // Note effect present +#define DMFPAT_VOLEFF 0x02 // Volume effect stored +// Sample flags +#define DMFSMP_LOOP 0x01 +#define DMFSMP_16BIT 0x02 +#define DMFSMP_COMPMASK 0x0C +#define DMFSMP_COMP1 0x04 // Compression type 1 +#define DMFSMP_COMP2 0x08 // Compression type 2 (unused) +#define DMFSMP_COMP3 0x0C // Compression type 3 (dito) +#define DMFSMP_LIBRARY 0x80 // Sample is stored in a library + #pragma pack(1) -typedef struct DMFHEADER +// DMF header +struct DMFHEADER { - DWORD id; // "DDMF" = 0x464d4444 - BYTE version; // 4 - CHAR trackername[8]; // "XTRACKER" - CHAR songname[30]; - CHAR composer[20]; - BYTE date[3]; -} DMFHEADER; + uint32 signature; // "DDMF" + uint8 version; // 1 - 7 are beta versions, 8 is the official thing, 10 is xtracker32 + char tracker[8]; // "XTRACKER" + char songname[30]; + char composer[20]; + uint8 creationDay; + uint8 creationMonth; + uint8 creationYear; +}; -typedef struct DMFINFO +struct DMF_IFFCHUNK { - DWORD id; // "INFO" - DWORD infosize; -} DMFINFO; + uint32 signature; // 4-letter identifier + uint32 chunksize; // chunk size without header +}; -typedef struct DMFSEQU +// Order list +struct DMFCHUNK_SEQUENCE { - DWORD id; // "SEQU" - DWORD seqsize; - WORD loopstart; - WORD loopend; - WORD sequ[2]; -} DMFSEQU; + uint16 loopStart; + uint16 loopEnd; + // order list follows here ... +}; -typedef struct DMFPATT +// Pattern header (global) +struct DMFCHUNK_PATTERNS { - DWORD id; // "PATT" - DWORD patsize; - WORD numpat; // 1-1024 - BYTE tracks; - BYTE firstpatinfo; -} DMFPATT; + uint16 numPatterns; // 1..1024 patterns + uint8 numTracks; // 1..32 channels +}; -typedef struct DMFTRACK +// Pattern header (for each pattern) +struct DMFCHUNK_PATTERNHEADER { - BYTE tracks; - BYTE beat; // [hi|lo] -> hi=ticks per beat, lo=beats per measure - WORD ticks; // max 512 - DWORD jmpsize; -} DMFTRACK; + uint8 numTracks; // 1..32 channels + uint8 beat; // [hi|lo] -> hi = rows per beat, lo = reserved + uint16 numRows; + uint32 patternLength; + // patttern data follows here ... +}; -typedef struct DMFSMPI +// Sample header +struct DMFCHUNK_SAMPLEHEADER { - DWORD id; - DWORD size; - BYTE samples; -} DMFSMPI; + uint32 length; + uint32 loopStart; + uint32 loopEnd; + uint16 c3freq; // 1000..45000hz + uint8 volume; // 0 = ignore + uint8 flags; +}; -typedef struct DMFSAMPLE +// Sample header tail (between head and tail, there might be the library name of the sample, depending on the DMF version) +struct DMFCHUNK_SAMPLEHEADERTAIL { - DWORD len; - DWORD loopstart; - DWORD loopend; - WORD c3speed; - BYTE volume; - BYTE flags; -} DMFSAMPLE; + uint16 filler; + uint32 crc32; +}; #pragma pack() +// Pattern translation memory +struct DMF_PATTERNSETTINGS +{ + uint8 beat; // Rows per beat + uint8 tempoTicks; // Tick mode param + uint8 tempoBPM; // BPM mode param + bool realBPMmode; // true = BPM mode + uint8 internalTicks; // Ticks per row in final pattern + vector<bool> playDir; // Sample play direction of each channel... false = forward (default) + vector<MODCOMMAND::NOTE> noteBuffer; // Note buffer + vector<MODCOMMAND::NOTE> lastNote; // Last played note on channel +}; -#ifdef DMFLOG -extern void Log(LPCSTR s, ...); -#endif - -// Convert portamento value (not very accurate, to say the least) -uint8 DMFporta2MPT(uint8 val) -//--------------------------- +// Convert portamento value (not very accurate due to X-Tracker's higher granularity, to say the least) +uint8 DMFporta2MPT(uint8 val, const uint8 internalTicks, const bool hasFine) +//-------------------------------------------------------------------------- { - if(val <= 0x0F) + if(val == 0) + return 0; + else if((val <= 0x0F || internalTicks < 2) && hasFine) return (val | 0xF0); else - return (val / 4); + return max(1, (val / (internalTicks - 1))); // no porta on first tick! } -bool CSoundFile::ReadDMF(const BYTE *lpStream, const DWORD dwMemLength) + +// Convert portamento / volume slide value (not very accurate due to X-Tracker's higher granularity, to say the least) +uint8 DMFslide2MPT(uint8 val, const uint8 internalTicks, const bool up) //--------------------------------------------------------------------- { - const DMFHEADER *pfh = (DMFHEADER *)lpStream; - DMFINFO *psi; - DMFSEQU *sequ; - DWORD dwMemPos; - BYTE infobyte[32]; - BYTE smplflags[MAX_SAMPLES]; + val = max(1, val / 4); + const bool isFine = (val < 0x0F) || (internalTicks < 2); + if(!isFine) + val = max(1, (val + 3) / (internalTicks - 1)); // no slides on first tick! +3 for rounding precision - if ((!lpStream) || (dwMemLength < 1024)) return false; - if ((pfh->id != 0x464d4444) || (!pfh->version) || (pfh->version & 0xF0)) return false; - dwMemPos = 66; - memcpy(m_szNames[0], pfh->songname, 30); - SpaceToNullStringFixed<30>(m_szNames[0]); - m_nType = MOD_TYPE_DMF; - m_dwSongFlags = SONG_LINEARSLIDES | SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS; - m_nChannels = 0; -#ifdef DMFLOG - Log("DMF version %d: \"%s\": %d bytes (0x%04X)\n", pfh->version, m_szNames[0], dwMemLength, dwMemLength); -#endif + if(up) + return (isFine ? 0x0F : 0x00) | (val << 4); + else + return (isFine ? 0xF0 : 0x00) | (val & 0x0F); -#ifdef MODPLUG_TRACKER - if(GetpModDoc() != nullptr) +} + + +// Calculate tremor on/off param +uint8 DMFtremor2MPT(uint8 val, const uint8 internalTicks) +//------------------------------------------------------- +{ + uint8 ontime = (val >> 4); + uint8 offtime = (val & 0x0F); + ontime = CLAMP(ontime * internalTicks / 15, 1, 15); + offtime = CLAMP(offtime * internalTicks / 15, 1, 15); + return (ontime << 4) | offtime; +} + + +// Calculate delay parameter for note cuts / delays +uint8 DMFdelay2MPT(uint8 val, const uint8 internalTicks) +//------------------------------------------------------ +{ + const int newval = (int)val * (int)internalTicks / 255; + return (uint8)CLAMP(newval, 0, 0x0F); +} + + +// Convert vibrato-style command parameters +uint8 DMFvibrato2MPT(uint8 val, const uint8 internalTicks) +//-------------------------------------------------------- +{ + // MPT: 1 vibrato period == 64 ticks... we have internalTicks ticks per row. + // X-Tracker: Period length specified in rows! + const int periodInTicks = max(1, (val >> 4)) * internalTicks; + const uint8 matchingPeriod = (uint8)CLAMP((128 / periodInTicks), 1, 15); + return (matchingPeriod << 4) | max(1, (val & 0x0F)); +} + + +PATTERNINDEX ConvertDMFPattern(const LPCBYTE lpStream, const DWORD dwMemLength, DMF_PATTERNSETTINGS &settings, CSoundFile *pSndFile) +//---------------------------------------------------------------------------------------------------------------------------------- +{ + #define ASSERT_CAN_READ_PATTERN(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwMemLength, x, return nPat); + + DWORD dwMemPos = 0; + + // ASSERT_CAN_READ_PATTERN(sizeof(DMFCHUNK_PATTERNHEADER)); -- already done in main loop + DMFCHUNK_PATTERNHEADER *patHead = (DMFCHUNK_PATTERNHEADER *)(lpStream + dwMemPos); + dwMemPos += sizeof(DMFCHUNK_PATTERNHEADER); + + const ROWINDEX numRows = CLAMP(LittleEndianW(patHead->numRows), 1, MAX_PATTERN_ROWS); + const PATTERNINDEX nPat = pSndFile->Patterns.Insert(numRows); + if(nPat == PATTERNINDEX_INVALID) { - FileHistory mptHistory; - MemsetZero(mptHistory); - mptHistory.loadDate.tm_mday = CLAMP(pfh->date[0], 0, 31); - mptHistory.loadDate.tm_mon = CLAMP(pfh->date[1], 1, 12) - 1; - mptHistory.loadDate.tm_year = pfh->date[2]; - GetpModDoc()->GetFileHistory()->clear(); - GetpModDoc()->GetFileHistory()->push_back(mptHistory); + return nPat; } -#endif // MODPLUG_TRACKER - while (dwMemPos + 7 < dwMemLength) + MODCOMMAND *m = pSndFile->Patterns[nPat]; + const CHANNELINDEX numChannels = min(pSndFile->GetNumChannels(), patHead->numTracks); + + // When breaking to a pattern with less channels that the previous pattern, + // all voices in the now unused channels are killed: + for(CHANNELINDEX nChn = numChannels + 1; nChn < pSndFile->GetNumChannels(); nChn++) { - DWORD id = *((LPDWORD)(lpStream+dwMemPos)); + m[nChn].note = NOTE_NOTECUT; + } - switch(id) + // Initialize tempo stuff + settings.beat = (patHead->beat >> 4); + bool tempoChange = settings.realBPMmode; + uint8 writeDelay = 0; + + // Counters for channel packing (including global track) + vector<uint8> channelCounter(numChannels + 1, 0); + + for(ROWINDEX nRow = 0; nRow < numRows; nRow++) + { + // Global track info counter reached 0 => read global track data + if(channelCounter[0] == 0) { - // "INFO" - case 0x4f464e49: - // "CMSG" - case 0x47534d43: - psi = (DMFINFO *)(lpStream+dwMemPos); - if (id == 0x47534d43) dwMemPos++; - if ((psi->infosize > dwMemLength) || (psi->infosize + dwMemPos + 8 > dwMemLength)) goto dmfexit; - if (psi->infosize >= 8) + ASSERT_CAN_READ_PATTERN(1); + uint8 globalInfo = lpStream[dwMemPos++]; + // 0x80: Packing counter (if not present, counter stays at 0) + if((globalInfo & DMFPAT_GLOBPACK) != 0) { - ReadFixedLineLengthMessage(lpStream + dwMemPos + 8, psi->infosize - 1, 40, 0); + ASSERT_CAN_READ_PATTERN(1); + channelCounter[0] = lpStream[dwMemPos++]; } - dwMemPos += psi->infosize + 8 - 1; - break; - // "SEQU" - case 0x55514553: - sequ = (DMFSEQU *)(lpStream+dwMemPos); - if ((sequ->seqsize >= dwMemLength) || (dwMemPos + sequ->seqsize + 12 > dwMemLength)) goto dmfexit; + globalInfo &= DMFPAT_GLOBMASK; + + uint8 globalData = 0; + if(globalInfo != 0) { - UINT nseq = sequ->seqsize >> 1; - if (nseq >= MAX_ORDERS-1) nseq = MAX_ORDERS-1; - Order.resize(nseq, Order.GetInvalidPatIndex()); - if (sequ->loopstart < nseq) m_nRestartPos = sequ->loopstart; - for (UINT i = 0; i < nseq - 2; i++) Order[i] = (PATTERNINDEX)sequ->sequ[i]; + ASSERT_CAN_READ_PATTERN(1); + globalData = lpStream[dwMemPos++]; } - dwMemPos += sequ->seqsize + 8; - break; - // "PATT" - case 0x54544150: - if (!m_nChannels) + switch(globalInfo) { - DMFPATT *patt = (DMFPATT *)(lpStream+dwMemPos); - UINT numpat; - DWORD dwPos = dwMemPos + 11; - if ((patt->patsize >= dwMemLength) || (dwMemPos + patt->patsize + 8 > dwMemLength)) goto dmfexit; - numpat = patt->numpat; - if (numpat > MAX_PATTERNS) numpat = MAX_PATTERNS; + case 1: // Set Tick Frame Speed + settings.realBPMmode = false; + settings.tempoTicks = max(1, globalData); // Tempo in 1/4 rows per second + settings.tempoBPM = 0; // Automatically updated by X-Tracker + tempoChange = true; + break; + case 2: // Set BPM Speed (real BPM mode) + if(globalData) // DATA = 0 doesn't do anything + { + settings.realBPMmode = true; + settings.tempoBPM = globalData; // Tempo in real BPM (depends on rows per beat) + if(settings.beat != 0) + { + settings.tempoTicks = (globalData * settings.beat * 15); // Automatically updated by X-Tracker + } + tempoChange = true; + } + break; + case 3: // Set Beat + settings.beat = (globalData >> 4); + if(settings.beat != 0) + { + // Tempo changes only if we're in real BPM mode + tempoChange = settings.realBPMmode; + } else + { + // If beat is 0, change to tick speed mode, but keep current tempo + settings.realBPMmode = false; + } + break; + case 4: // Tick Delay + writeDelay = globalData; + break; + case 5: // Set External Flag + break; + case 6: // Slide Speed Up + if(globalData > 0) + { + uint8 &tempoData = (settings.realBPMmode) ? settings.tempoBPM : settings.tempoTicks; + if(tempoData < 256 - globalData) + { + tempoData += globalData; + } else + { + tempoData = 255; + } + tempoChange = true; + } + break; + case 7: // Slide Speed Down + if(globalData > 0) + { + uint8 &tempoData = (settings.realBPMmode) ? settings.tempoBPM : settings.tempoTicks; + if(tempoData > 1 + globalData) + { + tempoData -= globalData; + } else + { + tempoData = 1; + } + tempoChange = true; + } + break; + } + } else + { + channelCounter[0]--; + } - m_nChannels = patt->tracks; - if (m_nChannels < patt->firstpatinfo) m_nChannels = patt->firstpatinfo; - if (m_nChannels > 32) m_nChannels = 32; - if (m_nChannels < 1) m_nChannels = 1; + // These will eventually be written to the pattern + int speed = 0, tempo = 0; - for (UINT npat=0; npat<numpat; npat++) + if(tempoChange) + { + // Can't do anything if we're in BPM mode and there's no rows per beat set... + if(!settings.realBPMmode || settings.beat) + { + // My approach to convert X-Tracker's "tick speed" (1/4 rows per second): + // Tempo * 6 / Speed = Beats per Minute + // => Tempo * 6 / (Speed * 60) = Beats per Second + // => Tempo * 24 / (Speed * 60) = Rows per Second (4 rows per beat at tempo 6) + // => Tempo = 60 * Rows per Second * Speed / 24 + // For some reason, using settings.tempoTicks + 1 gives more accurate results than just settings.tempoTicks... (same problem in the old libmodplug DMF loader) + // Original unoptimized formula: + //const int tickspeed = (tempoRealBPMmode) ? max(1, (tempoData * beat * 4) / 60) : tempoData; + const int tickspeed = (settings.realBPMmode) ? max(1, settings.tempoBPM * settings.beat * 2) : ((settings.tempoTicks + 1) * 30); + // Try to find matching speed - try higher speeds first, so that effects like arpeggio and tremor work better. + for(speed = 255; speed > 1; speed--) { - DMFTRACK *pt = (DMFTRACK *)(lpStream+dwPos); - #ifdef DMFLOG - Log("Pattern #%d: %d tracks, %d rows\n", npat, pt->tracks, pt->ticks); - #endif - UINT tracks = pt->tracks; - if (tracks > 32) tracks = 32; - UINT ticks = pt->ticks; - if (ticks > MAX_PATTERN_ROWS) ticks = MAX_PATTERN_ROWS; - if (ticks < 1) ticks = 1; - dwPos += 8; - if ((pt->jmpsize >= dwMemLength) || (dwPos + pt->jmpsize + 4 >= dwMemLength)) break; - if(Patterns.Insert(npat, ticks)) goto dmfexit; - MODCOMMAND *m = Patterns[npat]; + // Original unoptimized formula: + // tempo = 30 * tickspeed * speed / 48; + tempo = tickspeed * speed / 48; + if(tempo >= 32 && tempo <= 255) + { + break; + } + } + tempo = CLAMP(tempo, 32, 255); + settings.internalTicks = (uint8)speed; + } else + { + tempoChange = false; + } + } - // If pattern "width" changes, leftover voices are killed: - for(CHANNELINDEX nChn = tracks; nChn < m_nChannels; nChn++) + MODCOMMAND *m = pSndFile->Patterns[nPat].GetpModCommand(nRow, 1); // Reserve first channel for global effects + + for(CHANNELINDEX nChn = 1; nChn <= numChannels; nChn++, m++) + { + // Track info counter reached 0 => read track data + if(channelCounter[nChn] == 0) + { + ASSERT_CAN_READ_PATTERN(1); + const uint8 channelInfo = lpStream[dwMemPos++]; + // 0x80: Packing counter (if not present, counter stays at 0) + if((channelInfo & DMFPAT_COUNTER) != 0) + { + ASSERT_CAN_READ_PATTERN(1); + channelCounter[nChn] = lpStream[dwMemPos++]; + } + + // 0x40: Instrument + bool slideNote = true; // If there is no instrument number next to a note, the note is not retriggered! + if((channelInfo & DMFPAT_INSTR) != 0) + { + ASSERT_CAN_READ_PATTERN(1); + m->instr = lpStream[dwMemPos++]; + if(m->instr != 0) { - m[nChn].note = NOTE_NOTECUT; + slideNote = false; } + } - DWORD d = dwPos; - dwPos += pt->jmpsize; - UINT ttype = 1; - UINT tempo = 125; - UINT glbinfobyte = 0; - UINT pbeat = (pt->beat & 0xf0) ? pt->beat>>4 : 8; - BOOL tempochange = (pt->beat & 0xf0) ? TRUE : FALSE; - MemsetZero(infobyte); - for (UINT row=0; row<ticks; row++) + // 0x20: Note + if((channelInfo & DMFPAT_NOTE) != 0) + { + ASSERT_CAN_READ_PATTERN(1); + m->note = lpStream[dwMemPos++]; + if(m->note >= 1 && m->note <= 108) { - MODCOMMAND *p = &m[row * m_nChannels]; - // Parse track global effects - if (!glbinfobyte) + m->note += 24; + settings.lastNote[nChn] = m->note; + } else if(m->note >= 129 && m->note <= 236) + { + // "Buffer notes" for portamento (and other effects?) that are actually not played, but just "queued"... + settings.noteBuffer[nChn] = (m->note & 0x7F) + 24; + m->note = NOTE_NONE; + } else if(m->note == 255) + { + m->note = NOTE_NOTECUT; + } + } + + // If there's just an instrument number, but no note, retrigger sample. + if(m->note == NOTE_NONE && NOTE_IS_VALID(m->note) && m->instr > 0) + { + m->note = settings.lastNote[nChn]; + m->instr = 0; + } + + if(m->note != NOTE_NONE && NOTE_IS_VALID(m->note)) + { + settings.playDir[nChn] = false; + } + + uint8 effect1 = CMD_NONE, effect2 = CMD_NONE, effect3 = CMD_NONE; + uint8 effectParam1 = 0, effectParam2 = 0, effectParam3 = 0; + + // 0x10: Volume + if((channelInfo & DMFPAT_VOLUME) != 0) + { + ASSERT_CAN_READ_PATTERN(1); + m->volcmd = VOLCMD_VOLUME; + m->vol = (lpStream[dwMemPos++] + 3) / 4; + } + + // 0x08: Instrument effect + if((channelInfo & DMFPAT_INSEFF) != 0) + { + ASSERT_CAN_READ_PATTERN(2); + effect1 = lpStream[dwMemPos++]; + effectParam1 = lpStream[dwMemPos++]; + + switch(effect1) + { + case 1: // Stop Sample + m->note = NOTE_NOTECUT; + effect1 = CMD_NONE; + break; + case 2: // Stop Sample Loop + m->note = NOTE_KEYOFF; + effect1 = CMD_NONE; + break; + case 3: // Instrument Volume Override (aka "Restart") + m->note = settings.lastNote[nChn]; + settings.playDir[nChn] = false; + effect1 = CMD_NONE; + break; + case 4: // Sample Delay + effectParam1 = DMFdelay2MPT(effectParam1, settings.internalTicks); + if(effectParam1) { - BYTE info = lpStream[d++]; - BYTE infoval = 0; - if ((info & 0x80) && (d < dwPos)) glbinfobyte = lpStream[d++]; - info &= 0x7f; - if ((info) && (d < dwPos)) infoval = lpStream[d++]; - switch(info) - { - case 1: ttype = 0; tempo = infoval; tempochange = TRUE; break; - case 2: ttype = 1; tempo = infoval; tempochange = TRUE; break; - case 3: pbeat = infoval>>4; tempochange = ttype; break; - #ifdef DMFLOG - default: if (info) Log("GLB: %02X.%02X\n", info, infoval); - #endif - } + effect1 = CMD_S3MCMDEX; + effectParam1 = 0xD0 | (effectParam1); } else { - glbinfobyte--; + effect1 = CMD_NONE; } - // Parse channels - for (UINT i=0; i<tracks; i++) if (!infobyte[i]) + if(m->note == NOTE_NONE) { - MODCOMMAND cmd = MODCOMMAND::Empty(); - BYTE info = lpStream[d++]; - if (info & 0x80) infobyte[i] = lpStream[d++]; - // Instrument - if (info & 0x40) - { - cmd.instr = lpStream[d++]; - } - // Note - if (info & 0x20) - { - cmd.note = lpStream[d++]; - if (cmd.note >= 1 && cmd.note <= 108) - { - cmd.note += 24; - } else if (cmd.note >= 129 && cmd.note <= 236) - { - // "ghost notes" for portamento that are actually not played... how the hell should we treat them?! - cmd.note = (cmd.note & 0x7F) + 24; - } else if (cmd.note == 255) - { - cmd.note = NOTE_NOTECUT; - } - } - // Volume - if (info & 0x10) - { - cmd.volcmd = VOLCMD_VOLUME; - cmd.vol = (lpStream[d++]+3)>>2; - } - // Effect 1 - Instrument - if (info & 0x08) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Key Off - case 1: if (!cmd.note) cmd.note = NOTE_NOTECUT; break; - // 2: Stop Sample Loop - case 2: if (!cmd.note) cmd.note = NOTE_KEYOFF; break; - // 4: Sample Delay, in 1/256th rows - case 4: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 5: Retrig, in 1/256th rows - case 5: if (eval&0xe0) { cmd.command = CMD_RETRIG; cmd.param = (eval>>5); } break; - // 6: Offset - case 6: cmd.command = CMD_OFFSET; cmd.param = eval; break; - // 10: Tekkno Invert - case 10: cmd.command = CMD_S3MCMDEX; cmd.param = 0x9F; break; - #ifdef DMFLOG - default: Log("FX1: %02X.%02X\n", efx, eval); - #endif - } - } - // Effect 2 - Note - if (info & 0x04) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Finetune - case 1: if (eval&0xf0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>4)|0x20; } break; - // 2: Note Delay - case 2: if (eval&0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xD0; } break; - // 3: Arpeggio - case 3: if (eval) { cmd.command = CMD_ARPEGGIO; cmd.param = eval; } break; - // 4: Portamento Up - case 4: cmd.command = CMD_PORTAMENTOUP; cmd.param = DMFporta2MPT(eval); break; - // 5: Portamento Down - case 5: cmd.command = CMD_PORTAMENTODOWN; cmd.param = DMFporta2MPT(eval); break; - // 6: Tone Portamento - case 6: cmd.command = CMD_TONEPORTAMENTO; cmd.param = DMFporta2MPT(eval); break; - // 8: Vibrato Sine - // 9: Vibrato Triangle - // 10: Vibrato Square - case 8: - case 9: - case 10: - cmd.command = CMD_VIBRATO; - cmd.param = (0xF0 - (eval & 0xF0)) | ((eval & 0x0F) / 2); - break; - // 12: Note cut, in 1/256th rows - case 12: if (eval & 0xe0) { cmd.command = CMD_S3MCMDEX; cmd.param = (eval>>5)|0xc0; } - else if (!cmd.note) { cmd.note = NOTE_NOTECUT; } break; - #ifdef DMFLOG - default: Log("FX2: %02X.%02X\n", efx, eval); - #endif - } - } - // Effect 3 - Volume - if (info & 0x02) - { - BYTE efx = lpStream[d++]; - BYTE eval = lpStream[d++]; - switch(efx) - { - // 1: Vol Slide Up - case 1: if (eval == 0xff) break; - eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_VOLUMESLIDE; cmd.param = eval<<4; break; - // 2: Vol Slide Down - case 2: if (eval == 0xff) break; - eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_VOLUMESLIDE; cmd.param = eval; break; - // 3: Tremor - case 3: - cmd.command = CMD_TREMOR; cmd.param = eval; - break; - // 4: Tremolo Sine - // 5: Tremolo Triangle - // 6: Tremolo Square - case 4: - case 5: - case 6: - cmd.command = CMD_TREMOLO; - cmd.param = (0xF0 - (eval & 0xF0)) | ((eval & 0x0F) / 2); - break; - // 7: Set Pan - case 7: if (!cmd.volcmd) { cmd.volcmd = VOLCMD_PANNING; cmd.vol = (eval+3)>>2; } - else { cmd.command = CMD_PANNING8; cmd.param = eval; } break; - // 8: Pan Slide Left - case 8: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval << 4; break; - // 9: Pan Slide Right - case 9: eval = (eval+3)>>2; if (eval > 0x0f) eval = 0x0f; - cmd.command = CMD_PANNINGSLIDE; cmd.param = eval; break; - #ifdef DMFLOG - default: Log("FX3: %02X.%02X\n", efx, eval); - #endif - } - } + m->note = settings.lastNote[nChn]; + settings.playDir[nChn] = false; + } + break; + case 5: // Tremolo Retrig Sample (who invented those stupid effect names?) + effectParam1 = max(1, DMFdelay2MPT(effectParam1, settings.internalTicks)); + effect1 = CMD_RETRIG; + settings.playDir[nChn] = false; + break; + case 6: // Offset + case 7: // Offset + 64k + case 8: // Offset + 128k + case 9: // Offset + 192k + // Put high offset on previous row + if(nRow > 0) + { + pSndFile->TryWriteEffect(nPat, nRow - 1, CMD_S3MCMDEX, (0xA0 | (effect1 - 6)), false, nChn, false, weTryPreviousRow); + } + effect1 = CMD_OFFSET; + settings.playDir[nChn] = false; + break; + case 10: // Invert Sample play direction ("Tekkno Invert") + effect1 = CMD_S3MCMDEX; + if(settings.playDir[nChn] == false) + effectParam1 = 0x9F; + else + effectParam1 = 0x9E; + settings.playDir[nChn] = !settings.playDir[nChn]; + break; + default: + effect1 = CMD_NONE; + break; + } + } - // Note without instrument == just reset pitch, do not retrigger - if(cmd.instr == 0 && cmd.note != NOTE_NONE && NOTE_IS_VALID(cmd.note) && cmd.command != CMD_TONEPORTAMENTO) - { - if(cmd.volcmd == VOLCMD_NONE) - { - cmd.volcmd = VOLCMD_TONEPORTAMENTO; - cmd.vol = 9; - } else - { - cmd.command = CMD_TONEPORTAMENTO; - cmd.param = 0xFF; - } - } + // 0x04: Note effect + if((channelInfo & DMFPAT_NOTEEFF) != 0) + { + ASSERT_CAN_READ_PATTERN(2); + effect2 = lpStream[dwMemPos++]; + effectParam2 = lpStream[dwMemPos++]; - // Store effect - if (i < m_nChannels) p[i] = cmd; - if (d > dwPos) - { - #ifdef DMFLOG - Log("Unexpected EOP: row=%d\n", row); - #endif - break; - } + switch(effect2) + { + case 1: // Note Finetune + effect2 = (effectParam2 < 128) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN; + if(effectParam2 > 128) effectParam2 = 255 - effectParam2 + 1; + effectParam2 = 0xF0 | min(0x0F, effectParam2); // Well, this is not too accurate... + break; + case 2: // Note Delay (wtf is the difference to Sample Delay?) + effectParam2 = DMFdelay2MPT(effectParam2, settings.internalTicks); + if(effectParam2) + { + effect2 = CMD_S3MCMDEX; + effectParam2 = 0xD0 | (effectParam2); } else { - infobyte[i]--; + effect2 = CMD_NONE; } - - // Find free channel for tempo change - if (tempochange) + break; + case 3: // Arpeggio + effect2 = CMD_ARPEGGIO; + break; + case 4: // Portamento Up + case 5: // Portamento Down + effectParam2 = DMFporta2MPT(effectParam2, settings.internalTicks, true); + effect2 = (effect2 == 4) ? CMD_PORTAMENTOUP : CMD_PORTAMENTODOWN; + break; + case 6: // Portamento to Note + if(m->note == NOTE_NONE) { - tempochange = FALSE; - UINT speed=6, modtempo=tempo; - UINT rpm = ((ttype) && (pbeat)) ? tempo*pbeat : (tempo+1)*15; - for (speed=30; speed>1; speed--) - { - modtempo = rpm*speed/24; - if (modtempo <= 200) break; - if ((speed < 6) && (modtempo < 256)) break; - } - #ifdef DMFLOG - Log("Tempo change: ttype=%d pbeat=%d tempo=%3d -> speed=%d tempo=%d\n", - ttype, pbeat, tempo, speed, modtempo); - #endif - for (UINT ich=0; ich<m_nChannels; ich++) if (!p[ich].command) - { - if (speed) - { - p[ich].command = CMD_SPEED; - p[ich].param = (BYTE)speed; - speed = 0; - } else - if ((modtempo >= 32) && (modtempo < 256)) - { - p[ich].command = CMD_TEMPO; - p[ich].param = (BYTE)modtempo; - modtempo = 0; - } else - { - break; - } - } + m->note = settings.noteBuffer[nChn]; } - if (d >= dwPos) break; + effectParam2 = DMFporta2MPT(effectParam2, settings.internalTicks, false); + effect2 = CMD_TONEPORTAMENTO; + break; + case 7: // Scratch to Note (neat! but we don't have such an effect...) + m->note = effectParam2 + 25; + effect2 = CMD_TONEPORTAMENTO; + effectParam2 = 0xFF; + break; + case 8: // Vibrato Sine + case 9: // Vibrato Triangle (ramp down should be close enough) + case 10: // Vibrato Square + // Put vibrato type on previous row + if(nRow > 0) + { + pSndFile->TryWriteEffect(nPat, nRow - 1, CMD_S3MCMDEX, (0x30 | (effect2 - 8)), false, nChn, false, weTryPreviousRow); + } + effect2 = CMD_VIBRATO; + effectParam2 = DMFvibrato2MPT(effectParam2, settings.internalTicks); + break; + case 11: // Note Tremolo + effectParam2 = DMFtremor2MPT(effectParam2, settings.internalTicks); + effect2 = CMD_TREMOR; + break; + case 12: // Note Cut + effectParam2 = DMFdelay2MPT(effectParam2, settings.internalTicks); + if(effectParam2) + { + effect2 = CMD_S3MCMDEX; + effectParam2 = 0xC0 | (effectParam2); + } else + { + effect2 = CMD_NONE; + m->note = NOTE_NOTECUT; + } + break; + default: + effect2 = CMD_NONE; + break; } - #ifdef DMFLOG - Log(" %d/%d bytes remaining\n", dwPos-d, pt->jmpsize); - #endif - if (dwPos + 8 >= dwMemLength) break; } - dwMemPos += patt->patsize + 8; - } - break; - // "SMPI": Sample Info - case 0x49504d53: - { - DMFSMPI *pds = (DMFSMPI *)(lpStream+dwMemPos); - if (pds->size <= dwMemLength - dwMemPos) + // 0x02: Volume effect + if((channelInfo & DMFPAT_VOLEFF) != 0) { - DWORD dwPos = dwMemPos + 9; - m_nSamples = pds->samples; - if (m_nSamples >= MAX_SAMPLES) m_nSamples = MAX_SAMPLES-1; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) + ASSERT_CAN_READ_PATTERN(2); + effect3 = lpStream[dwMemPos++]; + effectParam3 = lpStream[dwMemPos++]; + + switch(effect3) { - UINT namelen = lpStream[dwPos]; - smplflags[iSmp] = 0; - if (dwPos+namelen+1+sizeof(DMFSAMPLE) > dwMemPos+pds->size+8) break; - if (namelen) + case 1: // Volume Slide Up + case 2: // Volume Slide Down + effectParam3 = DMFslide2MPT(effectParam3, settings.internalTicks, (effect3 == 1)); + effect3 = CMD_VOLUMESLIDE; + break; + case 3: // Volume Tremolo (actually this is Tremor) + effectParam3 = DMFtremor2MPT(effectParam3, settings.internalTicks); + effect3 = CMD_TREMOR; + break; + case 4: // Tremolo Sine + case 5: // Tremolo Triangle (ramp down should be close enough) + case 6: // Tremolo Square + // Put tremolo type on previous row + if(nRow > 0) { - UINT rlen = (namelen < 32) ? namelen : 31; - memcpy(m_szNames[iSmp], lpStream+dwPos+1, rlen); - SpaceToNullStringFixed(m_szNames[iSmp], rlen); + pSndFile->TryWriteEffect(nPat, nRow - 1, CMD_S3MCMDEX, (0x40 | (effect3 - 4)), false, nChn, false, weTryPreviousRow); } - dwPos += namelen + 1; - DMFSAMPLE *psh = (DMFSAMPLE *)(lpStream+dwPos); - MODSAMPLE *psmp = &Samples[iSmp]; - psmp->nLength = psh->len; - psmp->nSustainStart = psh->loopstart; - psmp->nSustainEnd = psh->loopend; - psmp->nC5Speed = psh->c3speed; - psmp->nGlobalVol = 64; - psmp->nVolume = (psh->volume) ? ((WORD)psh->volume)+1 : (WORD)256; - psmp->uFlags = (psh->flags & 2) ? CHN_16BIT : 0; - if (psmp->uFlags & CHN_16BIT) psmp->nLength >>= 1; - if (psh->flags & 1) psmp->uFlags |= CHN_SUSTAINLOOP; - smplflags[iSmp] = psh->flags; - dwPos += (pfh->version < 8) ? 22 : 30; - #ifdef DMFLOG - Log("SMPI %d/%d: len=%d flags=0x%02X\n", iSmp, m_nSamples, psmp->nLength, psh->flags); - #endif + effect3 = CMD_TREMOLO; + effectParam3 = DMFvibrato2MPT(effectParam3, settings.internalTicks); + break; + case 7: // Set Balance + effect3 = CMD_PANNING8; + break; + case 8: // Slide Balance Left + case 9: // Slide Balance Right + effectParam3 = DMFslide2MPT(effectParam3, settings.internalTicks, (effect3 == 8)); + effect3 = CMD_PANNINGSLIDE; + break; + case 10: // Balance Vibrato Left/Right (always sine modulated) + effect3 = CMD_PANBRELLO; + effectParam3 = DMFvibrato2MPT(effectParam3, settings.internalTicks); + break; + default: + effect3 = CMD_NONE; + break; } } - dwMemPos += pds->size + 8; + + // I guess this is close enough to "not retriggering the note" + if(slideNote && m->note != NOTE_NONE && NOTE_IS_VALID(m->note)) + { + if(effect2 == CMD_NONE) + { + effect2 = CMD_TONEPORTAMENTO; + effectParam2 = 0xFF; + } else if(effect3 == CMD_NONE && effect2 != CMD_TONEPORTAMENTO) // Tone portamentos normally go in effect #2 + { + effect3 = CMD_TONEPORTAMENTO; + effectParam3 = 0xFF; + } + } + // If one of the effects is unused, temporarily put volume commands in there + if(m->volcmd == VOLCMD_VOLUME) + { + if(effect2 == CMD_NONE) + { + effect2 = CMD_VOLUME; + effectParam2 = m->vol; + m->volcmd = VOLCMD_NONE; + } else if(effect3 == CMD_NONE) + { + effect3 = CMD_VOLUME; + effectParam3 = m->vol; + m->volcmd = VOLCMD_NONE; + } + } + + // Do that dance. + // Maybe I should quit rewriting this everywhere and make a generic version :P + int n; + for (n = 0; n < 4; n++) + { + if(CSoundFile::ConvertVolEffect(&effect2, &effectParam2, (n >> 1) ? true : false)) + { + n = 5; + break; + } + std::swap(effect2, effect3); + std::swap(effectParam2, effectParam3); + } + if (n < 5) + { + if (CSoundFile::GetEffectWeight((MODCOMMAND::COMMAND)effect2) > CSoundFile::GetEffectWeight((MODCOMMAND::COMMAND)effect3)) + { + std::swap(effect2, effect3); + std::swap(effectParam2, effectParam3); + } + effect2 = CMD_NONE; + } + if (!effect2) + effectParam2 = 0; + if (!effect3) + effectParam3 = 0; + + if(m->volcmd == VOLCMD_NONE && effect2 != VOLCMD_NONE) + { + m->volcmd = effect2; + m->vol = effectParam2; + } + // Prefer instrument effects over any other effects + if(effect1 != CMD_NONE) + { + m->command = effect1; + m->param = effectParam1; + } else if(effect3 != CMD_NONE) + { + m->command = effect3; + m->param = effectParam3; + } + + } else + { + channelCounter[nChn]--; } + } // End for all channels + + // Now we can try to write tempo information. + if(tempoChange) + { + tempoChange = false; + pSndFile->TryWriteEffect(nPat, nRow, CMD_TEMPO, (BYTE)tempo, false, 0, false, weTryNextRow); + pSndFile->TryWriteEffect(nPat, nRow, CMD_SPEED, (BYTE)speed, false, CHANNELINDEX_INVALID, false, weTryNextRow); + } + // Try to put delay effects somewhere as well + if(writeDelay & 0xF0) + { + pSndFile->TryWriteEffect(nPat, nRow, CMD_S3MCMDEX, 0xE0 | (writeDelay >> 4), false, CHANNELINDEX_INVALID, true, weIgnore); + } + if(writeDelay & 0x0F) + { + const uint8 param = (writeDelay & 0x0F) * settings.internalTicks / 15; + pSndFile->TryWriteEffect(nPat, nRow, CMD_S3MCMDEX, 0x60 | CLAMP(param, 1, 15), false, CHANNELINDEX_INVALID, true, weIgnore); + } + writeDelay = 0; + } // End for all rows + + return nPat; + + #undef ASSERT_CAN_READ_PATTERN + +} + + +DWORD ConvertDMFSample(const SAMPLEINDEX nSmp, const LPCBYTE lpStream, const DWORD dwMemLength, const bool isV8, uint8 &sampleFlags, CSoundFile *pSndFile) +//-------------------------------------------------------------------------------------------------------------------------------------------------------- +{ + #define ASSERT_CAN_READ_SAMPLE(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwMemLength, x, return 0); + + DWORD dwMemPos = 0; + + ASSERT_CAN_READ_SAMPLE(1); + const size_t lenName = lpStream[dwMemPos++]; + STATIC_ASSERT(MAX_SAMPLENAME > 30); + const size_t lenNameImport = min(30, lenName); + ASSERT_CAN_READ_SAMPLE(lenName); + memcpy(pSndFile->m_szNames[nSmp], lpStream + dwMemPos, lenNameImport); + SpaceToNullStringFixed(pSndFile->m_szNames[nSmp], lenNameImport); + dwMemPos += lenName; + + ASSERT_CAN_READ_SAMPLE(sizeof(DMFCHUNK_SAMPLEHEADER)); + DMFCHUNK_SAMPLEHEADER *smpHead = (DMFCHUNK_SAMPLEHEADER *)(lpStream + dwMemPos); + dwMemPos += sizeof(DMFCHUNK_SAMPLEHEADER); + + MODSAMPLE *pSmp = &pSndFile->Samples[nSmp]; + MemsetZero(*pSmp); + pSmp->nLength = min(MAX_SAMPLE_LENGTH, LittleEndian(smpHead->length)); + pSmp->nSustainEnd = min(pSmp->nLength, LittleEndian(smpHead->loopEnd)); + pSmp->nSustainStart = min(pSmp->nSustainEnd, LittleEndian(smpHead->loopStart)); + if(pSmp->nSustainEnd > 0) + { + pSmp->nSustainEnd--; + } + + pSmp->nC5Speed = LittleEndianW(smpHead->c3freq); + pSmp->nGlobalVol = 64; + if(smpHead->volume) + { + pSmp->nVolume = smpHead->volume + 1; + } else + { + pSmp->nVolume = 256; + } + sampleFlags = smpHead->flags; + pSmp->uFlags = 0; + if((sampleFlags & DMFSMP_LOOP) != 0 && pSmp->nSustainEnd > pSmp->nSustainStart) + { + pSmp->uFlags |= CHN_SUSTAINLOOP; + } + if((sampleFlags & DMFSMP_16BIT) != 0) + { + pSmp->uFlags |= CHN_16BIT; + pSmp->nLength /= 2; + pSmp->nSustainStart /= 2; + pSmp->nSustainEnd /= 2; + } + + if(isV8) + { + // Read library name in version 8 files + ASSERT_CAN_READ_SAMPLE(8); + memcpy(pSmp->filename, lpStream + dwMemPos, 8); + SpaceToNullStringFixed<8>(pSmp->filename); + dwMemPos += 8; + } + + ASSERT_CAN_READ_SAMPLE(sizeof(DMFCHUNK_SAMPLEHEADERTAIL)); + // We don't care for the checksum of the sample data... + dwMemPos += sizeof(DMFCHUNK_SAMPLEHEADERTAIL); + + return dwMemPos; + + #undef ASSERT_CAN_READ_SAMPLE + +} + + +bool CSoundFile::ReadDMF(const BYTE *lpStream, const DWORD dwMemLength) +//--------------------------------------------------------------------- +{ + #define ASSERT_CAN_READ_CHUNK(x) ASSERT_CAN_READ_PROTOTYPE(dwMemPos, dwChunkEnd, x, break); + + DWORD dwMemPos = 0; + + ASSERT_CAN_READ(sizeof(DMFHEADER)); + DMFHEADER *pHeader = (DMFHEADER *)lpStream; + if(pHeader->signature != LittleEndian(DMF_DDMF) || !pHeader->version || pHeader->version > 10) + { + return false; + } + dwMemPos += sizeof(DMFHEADER); + + memcpy(m_szNames[0], pHeader->songname, 30); + SpaceToNullStringFixed<30>(m_szNames[0]); + m_nChannels = 0; + +#ifdef MODPLUG_TRACKER + if(GetpModDoc() != nullptr) + { + FileHistory mptHistory; + MemsetZero(mptHistory); + mptHistory.loadDate.tm_mday = CLAMP(pHeader->creationDay, 0, 31); + mptHistory.loadDate.tm_mon = CLAMP(pHeader->creationMonth, 1, 12) - 1; + mptHistory.loadDate.tm_year = pHeader->creationYear; + GetpModDoc()->GetFileHistory()->clear(); + GetpModDoc()->GetFileHistory()->push_back(mptHistory); + } +#endif // MODPLUG_TRACKER + + vector<uint8> sampleFlags; + vector<DWORD> patternOffset; + vector<DWORD> patternLength; + + ORDERINDEX loopStart = 0, loopEnd = ORDERINDEX_INVALID; + + // go through all chunks now + while(dwMemPos < dwMemLength) + { + // Special case: Last 4 bytes should be "ENDE", without a size field (WTF) + ASSERT_CAN_READ(4); + if(LittleEndian(*(uint32 *)(lpStream + dwMemPos)) == DMF_ENDE) + { break; + } - // "SMPD": Sample Data - case 0x44504d53: + ASSERT_CAN_READ(sizeof(DMF_IFFCHUNK)); + DMF_IFFCHUNK chunkheader = *(DMF_IFFCHUNK *)(lpStream + dwMemPos); + dwMemPos += sizeof(DMF_IFFCHUNK); + + chunkheader.signature = LittleEndian(chunkheader.signature); + chunkheader.chunksize = LittleEndian(chunkheader.chunksize); + ASSERT_CAN_READ(chunkheader.chunksize); + + const DWORD dwChunkEnd = dwMemPos + chunkheader.chunksize; + + switch(chunkheader.signature) + { + case DMF_CMSG: // "CMSG" - Song message + ASSERT_CAN_READ_CHUNK(1); + dwMemPos++; // filler byte + ReadFixedLineLengthMessage(lpStream + dwMemPos, chunkheader.chunksize - 1, 40, 0); + break; + + case DMF_SEQU: // "SEQU" - Order list { - DWORD dwPos = dwMemPos + 8; - UINT ismpd = 0; - for (UINT iSmp=1; iSmp<=m_nSamples; iSmp++) + ASSERT_CAN_READ_CHUNK(sizeof(DMFCHUNK_SEQUENCE)); + DMFCHUNK_SEQUENCE *seqHead = (DMFCHUNK_SEQUENCE *)(lpStream + dwMemPos); + dwMemPos += sizeof(DMFCHUNK_SEQUENCE); + + loopStart = LittleEndianW(seqHead->loopStart); + loopEnd = LittleEndianW(seqHead->loopEnd); + const ORDERINDEX numOrders = (ORDERINDEX)min(MAX_ORDERS, (chunkheader.chunksize - sizeof(DMFCHUNK_SEQUENCE)) / 2); + Order.resize(numOrders, Order.GetInvalidPatIndex()); + + for(ORDERINDEX i = 0; i < numOrders; i++, dwMemPos += 2) { - ismpd++; - DWORD pksize; - if (dwPos + 4 >= dwMemLength) + uint16 orderItem = *(uint16 *)(lpStream + dwMemPos); + Order[i] = (PATTERNINDEX)LittleEndianW(orderItem); + } + } + break; + + case DMF_PATT: // "PATT" - Pattern data + if(m_nChannels == 0) + { + ASSERT_CAN_READ_CHUNK(sizeof(DMFCHUNK_PATTERNS)); + DMFCHUNK_PATTERNS *patInfo = (DMFCHUNK_PATTERNS *)(lpStream + dwMemPos); + dwMemPos += sizeof(DMFCHUNK_PATTERNS); + m_nChannels = CLAMP(patInfo->numTracks, 1, 32) + 1; // + 1 for global track (used for tempo stuff) + + const PATTERNINDEX numPats = min(MAX_PATTERNS, LittleEndianW(patInfo->numPatterns)); + patternOffset.assign(numPats, 0); + patternLength.assign(numPats, 0); + + for(PATTERNINDEX nPat = 0; nPat < numPats; nPat++) + { + ASSERT_CAN_READ_CHUNK(sizeof(DMFCHUNK_PATTERNHEADER)); + DMFCHUNK_PATTERNHEADER *patHead = (DMFCHUNK_PATTERNHEADER *)(lpStream + dwMemPos); + + patternOffset[nPat] = dwMemPos; + patternLength[nPat] = sizeof(DMFCHUNK_PATTERNHEADER) + LittleEndian(patHead->patternLength); + + ASSERT_CAN_READ_CHUNK(patternLength[nPat]); + dwMemPos += patternLength[nPat]; + } + } + break; + + case DMF_SMPI: // "SMPI" - Sample headers + if(m_nSamples == 0) + { + ASSERT_CAN_READ_CHUNK(1); + m_nSamples = (SAMPLEINDEX)min(MAX_SAMPLES - 1, lpStream[dwMemPos]); + dwMemPos++; + + sampleFlags.assign(m_nSamples, 0); + for(SAMPLEINDEX nSmp = 0; nSmp < m_nSamples; nSmp++) + { + const DWORD bytesRead = ConvertDMFSample(nSmp + 1, lpStream + dwMemPos, dwChunkEnd - dwMemPos, (pHeader->version >= 8), sampleFlags[nSmp], this); + if(bytesRead == 0) { - #ifdef DMFLOG - Log("Unexpected EOF at sample %d/%d! (pos=%d)\n", iSmp, m_nSamples, dwPos); - #endif break; } - pksize = *((LPDWORD)(lpStream+dwPos)); - #ifdef DMFLOG - Log("sample %d: pos=0x%X pksize=%d ", iSmp, dwPos, pksize); - Log("len=%d flags=0x%X [%08X]\n", Samples[iSmp].nLength, smplflags[ismpd], *((LPDWORD)(lpStream+dwPos+4))); - #endif - dwPos += 4; - if (pksize > dwMemLength - dwPos) + dwMemPos += bytesRead; + } + + } + break; + + case DMF_SMPD: // "SMPD" - Sample data + for(SAMPLEINDEX nSmp = 1; nSmp <= m_nSamples; nSmp++) + { + ASSERT_CAN_READ_CHUNK(4); + const uint32 length = LittleEndian(*(uint32 *)(lpStream + dwMemPos)); + dwMemPos += 4; + ASSERT_CAN_READ_CHUNK(length); + + if(length > 0) + { + UINT flags = (Samples[nSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; + if((sampleFlags[nSmp - 1] & DMFSMP_COMPMASK) == DMFSMP_COMP1) { - #ifdef DMFLOG - Log("WARNING: pksize=%d, but only %d bytes left\n", pksize, dwMemLength-dwPos); - #endif - pksize = dwMemLength - dwPos; + flags = (Samples[nSmp].uFlags & CHN_16BIT) ? RS_DMF16 : RS_DMF8; } - if ((pksize) && (iSmp <= m_nSamples)) - { - UINT flags = (Samples[iSmp].uFlags & CHN_16BIT) ? RS_PCM16S : RS_PCM8S; - if (smplflags[ismpd] & 4) flags = (Samples[iSmp].uFlags & CHN_16BIT) ? RS_DMF16 : RS_DMF8; - ReadSample(&Samples[iSmp], flags, (LPSTR)(lpStream+dwPos), pksize); - } - dwPos += pksize; + ReadSample(&Samples[nSmp], flags, (LPCSTR)(lpStream + dwMemPos), length); + dwMemPos += length; } - dwMemPos = dwPos; } break; - // "ENDE": end of file - case 0x45444e45: - goto dmfexit; - - // Unrecognized id, or "ENDE" field + case DMF_SMPJ: // "SMPJ" - Sample jump points (xtracker32 only) + break; + +#if 0 default: - dwMemPos += 4; - break; + // There is some (encrypted?) IFF chunk with a very weird ID at the end of many DMF files. What does it mean? + { + char s[32]; + const char *sig = (char *)&chunkheader.signature; + wsprintf(s, "Unknown chunk ID %c%c%c%c at %d", sig[0], sig[1], sig[2], sig[3], dwMemPos - sizeof(DMF_IFFCHUNK)); + MessageBox(0, s, 0, 0); + } +#endif } + + dwMemPos = dwChunkEnd; } -dmfexit: - if (!m_nChannels) + + if(!patternOffset.empty()) { - if (!m_nSamples) + DMF_PATTERNSETTINGS settings; + settings.beat = 0; + settings.tempoTicks = 32; + settings.tempoBPM = 120; + settings.realBPMmode = false; + settings.internalTicks = 6; + settings.playDir.assign(GetNumChannels(), false); + settings.noteBuffer.assign(GetNumChannels(), NOTE_NONE); + settings.lastNote.assign(GetNumChannels(), NOTE_NONE); + + for(ORDERINDEX nOrd = 0; nOrd < Order.GetLength(); nOrd++) { - m_nType = MOD_TYPE_NONE; - return false; + // Create one pattern for each order item, as the same pattern can be played with different settings + PATTERNINDEX nPat = Order[nOrd]; + if(nPat < patternOffset.size() && patternOffset[nPat] != 0) + { + nPat = ConvertDMFPattern(lpStream + patternOffset[nPat], patternLength[nPat], settings, this); + Order[nOrd] = nPat; + // Loop end? + if(nPat != PATTERNINDEX_INVALID && nOrd == loopEnd && (loopStart > 0 || nOrd < Order.GetLength() - 1)) + { + TryWriteEffect(nPat, Patterns[nPat].GetNumRows() - 1, CMD_POSITIONJUMP, (BYTE)loopStart, false, CHANNELINDEX_INVALID, false, weTryPreviousRow); + } + } } - m_nChannels = 4; } + + m_nType = MOD_TYPE_DMF; + m_dwSongFlags = SONG_LINEARSLIDES | SONG_ITCOMPATGXX; // this will be converted to IT format by MPT. SONG_ITOLDEFFECTS is not set because of tremor. + SetModFlag(MSF_COMPATIBLE_PLAY, true); + m_nDefaultSpeed = 6; + m_nDefaultTempo = 120; + m_nDefaultGlobalVolume = 256; + m_nSamplePreAmp = m_nVSTiVolume = 48; + return true; + + #undef ASSERT_CAN_READ_CHUNK } /////////////////////////////////////////////////////////////////////// -// DMF Compression +// DMF Compression (from libmodplug) -#pragma pack(1) - typedef struct DMF_HNODE { - short int left, right; - BYTE value; + int16 left, right; + uint8 value; } DMF_HNODE; typedef struct DMF_HTREE { - LPBYTE ibuf, ibufmax; - DWORD bitbuf; - UINT bitnum; - UINT lastnode, nodecount; + uint8 *ibuf, *ibufmax; + uint32 bitbuf; + int bitnum; + int lastnode, nodecount; DMF_HNODE nodes[256]; } DMF_HTREE; -#pragma pack() - // DMF Huffman ReadBits BYTE DMFReadBits(DMF_HTREE *tree, UINT nbits) //------------------------------------------- { - BYTE x = 0, bitv = 1; + uint8 x = 0, bitv = 1; while (nbits--) { if (tree->bitnum) @@ -608,8 +1065,8 @@ void DMFNewNode(DMF_HTREE *tree) //------------------------------ { - BYTE isleft, isright; - UINT actnode; + uint8 isleft, isright; + int actnode; actnode = tree->nodecount; if (actnode > 255) return; @@ -622,7 +1079,7 @@ tree->lastnode = tree->nodecount; if (isleft) { - tree->nodes[actnode].left = tree->lastnode; + tree->nodes[actnode].left = (int16)tree->lastnode; DMFNewNode(tree); } else { @@ -631,7 +1088,7 @@ tree->lastnode = tree->nodecount; if (isright) { - tree->nodes[actnode].right = tree->lastnode; + tree->nodes[actnode].right = (int16)tree->lastnode; DMFNewNode(tree); } else { @@ -640,19 +1097,20 @@ } -int DMFUnpack(LPBYTE psample, LPBYTE ibuf, LPBYTE ibufmax, UINT maxlen) -//---------------------------------------------------------------------- +int DMFUnpack(LPBYTE psample, uint8 *ibuf, uint8 *ibufmax, UINT maxlen) +//--------------------------------------------------------------------- { DMF_HTREE tree; - UINT actnode; - BYTE value, sign, delta = 0; + int actnode; + uint8 value, sign, delta = 0; MemsetZero(tree); tree.ibuf = ibuf; tree.ibufmax = ibufmax; DMFNewNode(&tree); value = 0; - for (UINT i=0; i<maxlen; i++) + + for (int i = 0; i < maxlen; i++) { actnode = 0; sign = DMFReadBits(&tree, 1); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-12 21:46:17
|
Revision: 848 http://modplug.svn.sourceforge.net/modplug/?rev=848&view=rev Author: saga-games Date: 2011-04-12 21:46:10 +0000 (Tue, 12 Apr 2011) Log Message: ----------- [New] The channel headers can now be dragged around to move channels. Holding shift while dragging duplicates the channel. [Imp] Moving channels can now be undone. Modified Paths: -------------- trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/MainFrm.cpp trunk/OpenMPT/mptrack/Mainfrm.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/soundlib/Sndfile.cpp Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2011-04-11 19:53:15 UTC (rev 847) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2011-04-12 21:46:10 UTC (rev 848) @@ -314,7 +314,7 @@ //--------------------------------------------------------------------------- { PCPATTERNFONT pfnt = GetCurrentPatternFont(); - + UINT xsrc = pfnt->nNoteX, ysrc = pfnt->nNoteY, dx = pfnt->nEltWidths[0]; if (!note) { @@ -471,6 +471,7 @@ rect.right = m_szHeader.cx; DrawButtonRect(hdc, &rect, s, FALSE, ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PATTERNHEADER)) ? TRUE : FALSE); + // Drawing Channel Headers while (xpaint < rcClient.right) { @@ -482,7 +483,7 @@ const char *pszfmt = pSndFile->m_bChannelMuteTogglePending[ncolhdr]? "[Channel %d]" : "Channel %d"; // const char *pszfmt = pModDoc->IsChannelRecord(ncolhdr) ? "Channel %d " : "Channel %d"; // -! NEW_FEATURE#0012 - if ((pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT)) && ((BYTE)pSndFile->ChnSettings[ncolhdr].szName[0] >= 0x20)) + if ((pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT)) && ((BYTE)pSndFile->ChnSettings[ncolhdr].szName[0] >= ' ')) pszfmt = pSndFile->m_bChannelMuteTogglePending[ncolhdr]?"%d: [%s]":"%d: %s"; else if (m_nDetailLevel < 2) pszfmt = pSndFile->m_bChannelMuteTogglePending[ncolhdr]?"[Ch%d]":"Ch%d"; else if (m_nDetailLevel < 3) pszfmt = pSndFile->m_bChannelMuteTogglePending[ncolhdr]?"[Chn %d]":"Chn %d"; @@ -491,12 +492,28 @@ // -> DESC="midi keyboard split" // DrawButtonRect(hdc, &rect, s, // (pSndFile->ChnSettings[ncolhdr].dwFlags & CHN_MUTE) ? TRUE : FALSE, -// ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) && ((m_nDragItem & 0xFFFF) == ncolhdr)) ? TRUE : FALSE, DT_CENTER); +// ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, DT_CENTER); // rect.bottom = rect.top + COLHDR_HEIGHT; DrawButtonRect(hdc, &rect, s, (pSndFile->ChnSettings[ncolhdr].dwFlags & CHN_MUTE) ? TRUE : FALSE, - ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) && ((m_nDragItem & 0xFFFF) == ncolhdr)) ? TRUE : FALSE, + ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, pModDoc->IsChannelRecord(ncolhdr) ? DT_RIGHT : DT_CENTER); + + // When dragging around channel headers, mark insertion position + if(m_bDragging && !m_bInItemRect + && (m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER + && (m_nDropItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER + && (m_nDropItem & DRAGITEM_VALUEMASK) == ncolhdr) + { + RECT r; + r.top = rect.top; + r.bottom = rect.bottom; + // Drop position depends on whether hovered channel is left or right of dragged item. + r.left = ((m_nDropItem & DRAGITEM_VALUEMASK) < (m_nDragItem & DRAGITEM_VALUEMASK) || m_bShiftDragging) ? rect.left : rect.right - 3; + r.right = r.left + 2; + ::FillRect(hdc, &r, CMainFrame::brushText); + } + rect.bottom = rect.top + COLHDR_HEIGHT; CRect insRect; @@ -543,8 +560,9 @@ wsprintf(s, "---"); } DrawButtonRect(hdc, &rect, s, FALSE, - ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PLUGNAME) && ((m_nDragItem & 0xFFFF) == ncolhdr)) ? TRUE : FALSE, DT_CENTER); + ((m_bInItemRect) && ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_PLUGNAME) && ((m_nDragItem & DRAGITEM_VALUEMASK) == ncolhdr)) ? TRUE : FALSE, DT_CENTER); } + } else break; ncolhdr++; xpaint += nColumnWidth; Modified: trunk/OpenMPT/mptrack/MainFrm.cpp =================================================================== --- trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-11 19:53:15 UTC (rev 847) +++ trunk/OpenMPT/mptrack/MainFrm.cpp 2011-04-12 21:46:10 UTC (rev 848) @@ -229,6 +229,7 @@ HBRUSH CMainFrame::brushGray = NULL; HBRUSH CMainFrame::brushBlack = NULL; HBRUSH CMainFrame::brushWhite = NULL; +HBRUSH CMainFrame::brushText = NULL; //CBrush *CMainFrame::pbrushBlack = NULL;//rewbs.envRowGrid //CBrush *CMainFrame::pbrushWhite = NULL;//rewbs.envRowGrid @@ -809,6 +810,7 @@ if (m_hGUIFont == NULL) m_hGUIFont = (HFONT)GetStockObject(ANSI_VAR_FONT); brushBlack = (HBRUSH)::GetStockObject(BLACK_BRUSH); brushWhite = (HBRUSH)::GetStockObject(WHITE_BRUSH); + brushText = ::CreateSolidBrush(GetSysColor(COLOR_BTNTEXT)); brushGray = ::CreateSolidBrush(GetSysColor(COLOR_BTNFACE)); penLightGray = ::CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNHIGHLIGHT)); penDarkGray = ::CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW)); Modified: trunk/OpenMPT/mptrack/Mainfrm.h =================================================================== --- trunk/OpenMPT/mptrack/Mainfrm.h 2011-04-11 19:53:15 UTC (rev 847) +++ trunk/OpenMPT/mptrack/Mainfrm.h 2011-04-12 21:46:10 UTC (rev 848) @@ -442,7 +442,7 @@ // GDI static HICON m_hIcon; static HFONT m_hGUIFont, m_hFixedFont, m_hLargeFixedFont; - static HBRUSH brushGray, brushBlack, brushWhite, brushHighLight, brushHighLightRed, brushWindow, brushYellow; + static HBRUSH brushGray, brushBlack, brushWhite, brushText, brushHighLight, brushHighLightRed, brushWindow, brushYellow; // static CBrush *pbrushBlack, *pbrushWhite; static HPEN penBlack, penDarkGray, penLightGray, penWhite, penHalfDarkGray, penSample, penEnvelope, penEnvelopeHighlight, penSeparator, penScratch, penGray00, penGray33, penGray40, penGray55, penGray80, penGray99, penGraycc, penGrayff; static HCURSOR curDragging, curNoDrop, curArrow, curNoDrop2, curVSplit; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-11 19:53:15 UTC (rev 847) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-12 21:46:10 UTC (rev 848) @@ -471,7 +471,7 @@ GetClientRect(&rcClient); xofs = GetXScrollPos(); yofs = GetYScrollPos(); - rect.SetRect(m_szHeader.cx, 0, m_szHeader.cx + GetColumnWidth() - 2, m_szHeader.cy); + rect.SetRect(m_szHeader.cx, 0, m_szHeader.cx + GetColumnWidth() /*- 2*/, m_szHeader.cy); plugRect.SetRect(m_szHeader.cx, m_szHeader.cy-PLUGNAME_HEIGHT, m_szHeader.cx + GetColumnWidth() - 2, m_szHeader.cy); //rewbs.patPlugNames pSndFile = pModDoc->GetSoundFile(); const UINT nmax = pSndFile->GetNumChannels(); @@ -1029,6 +1029,9 @@ m_nDragItem = GetDragItem(point, &m_rcDragItem); m_bDragging = true; m_bInItemRect = true; + m_bShiftDragging = false; + m_nDropItem = 0; + SetCapture(); if ((point.x >= m_szHeader.cx) && (point.y <= m_szHeader.cy)) { @@ -1121,8 +1124,12 @@ //------------------------------------------------------- { CModDoc *pModDoc = GetDocument(); - const bool bItemSelected = m_bInItemRect; + + const bool bItemSelected = m_bInItemRect || ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER); if (/*(!m_bDragging) ||*/ (!pModDoc)) return; + + CSoundFile *pSndFile = pModDoc->GetSoundFile(); + m_bDragging = false; m_bInItemRect = false; ReleaseCapture(); @@ -1158,31 +1165,82 @@ } if ((!bItemSelected) || (!m_nDragItem)) return; InvalidateRect(&m_rcDragItem, FALSE); - DWORD nItemNo = m_nDragItem & 0xFFFF; + const DWORD nItemNo = (m_nDragItem & DRAGITEM_VALUEMASK); + const DWORD nTargetNo = (m_nDropItem != 0) ? (m_nDropItem & DRAGITEM_VALUEMASK) : nItemNo; + switch(m_nDragItem & DRAGITEM_MASK) { case DRAGITEM_CHNHEADER: - if (nFlags & MK_SHIFT) { - if (nItemNo < MAX_CHANNELS) { - pModDoc->Record1Channel(nItemNo); - InvalidateChannelsHeaders(); + if(nItemNo == nTargetNo) + { + // Just clicked a channel header... + + if (nFlags & MK_SHIFT) + { + if (nItemNo < MAX_BASECHANNELS) + { + pModDoc->Record1Channel(nItemNo); + InvalidateChannelsHeaders(); + } } - } - else if (!(nFlags&MK_CONTROL)) + else if (!(nFlags & MK_CONTROL)) + { + pModDoc->MuteChannel(nItemNo, !pModDoc->IsChannelMuted(nItemNo)); + pModDoc->UpdateAllViews(this, HINT_MODCHANNELS | ((nItemNo / CHANNELS_IN_TAB) << HINT_SHIFT_CHNTAB)); + } + } else if(nTargetNo < pSndFile->GetNumChannels()) { - pModDoc->MuteChannel(nItemNo, !pModDoc->IsChannelMuted(nItemNo)); - pModDoc->UpdateAllViews(this, HINT_MODCHANNELS | ((nItemNo / CHANNELS_IN_TAB) << HINT_SHIFT_CHNTAB)); + // Dragged to other channel header => move or copy channel + + InvalidateRect(&m_rcDropItem, FALSE); + + const bool duplicate = (nFlags & MK_SHIFT) ? true : false; + vector<CHANNELINDEX> channels(pSndFile->GetNumChannels() + (duplicate ? 1 : 0), 0); + CHANNELINDEX i = 0; + bool modified = duplicate; + + for(CHANNELINDEX nChn = 0; nChn < pSndFile->GetNumChannels(); nChn++) + { + if(nChn == nTargetNo) + { + channels[nChn] = nItemNo; + } + else + { + if(i == nItemNo && !duplicate) // Don't want that source channel twice if we're just moving + { + i++; + } + channels[nChn] = i++; + } + if(channels[nChn] != nChn) + { + modified = true; + } + } + if(modified && pSndFile->ReArrangeChannels(channels) != 0) + { + if(duplicate) + { + pModDoc->UpdateAllViews(this, HINT_MODCHANNELS); + pModDoc->UpdateAllViews(this, HINT_MODTYPE); + SetCurrentPattern(m_nPattern); + } + InvalidatePattern(); + pModDoc->SetModified(); + } } break; case DRAGITEM_PATTERNHEADER: OnPatternProperties(); break; case DRAGITEM_PLUGNAME: //rewbs.patPlugNames - if (nItemNo < MAX_CHANNELS) { + if (nItemNo < MAX_BASECHANNELS) TogglePluginEditor(nItemNo); - } break; } + + m_nDropItem = 0; } @@ -1319,15 +1377,18 @@ //CSoundFile *pSndFile = pModDoc->GetSoundFile(); m_nDragItem = GetDragItem(point, &m_rcDragItem); - DWORD nItemNo = m_nDragItem & 0xFFFF; - switch(m_nDragItem & DRAGITEM_MASK) { - case DRAGITEM_CHNHEADER: - if (nFlags & MK_SHIFT) { - if (nItemNo < MAX_CHANNELS) { - pModDoc->Record2Channel(nItemNo); - InvalidateChannelsHeaders(); - } + DWORD nItemNo = m_nDragItem & DRAGITEM_VALUEMASK; + switch(m_nDragItem & DRAGITEM_MASK) + { + case DRAGITEM_CHNHEADER: + if (nFlags & MK_SHIFT) + { + if (nItemNo < MAX_BASECHANNELS) + { + pModDoc->Record2Channel(nItemNo); + InvalidateChannelsHeaders(); } + } break; } @@ -1335,21 +1396,35 @@ } -void CViewPattern::OnMouseMove(UINT, CPoint point) -//------------------------------------------------ +void CViewPattern::OnMouseMove(UINT nFlags, CPoint point) +//------------------------------------------------------- { if (!m_bDragging) return; + if (m_nDragItem) { - DWORD nItem = GetDragItem(point, NULL); - bool b = (nItem == m_nDragItem) ? true : false; - if (b != m_bInItemRect) + const CRect oldDropRect = m_rcDropItem; + const DWORD oldDropItem = m_nDropItem; + + m_bShiftDragging = (nFlags & MK_SHIFT) ? true : false; + m_nDropItem = GetDragItem(point, &m_rcDropItem); + + const bool b = (m_nDropItem == m_nDragItem) ? true : false; + const bool dragChannel = (m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER; + + if (b != m_bInItemRect || (m_nDropItem != oldDropItem && dragChannel)) { m_bInItemRect = b; InvalidateRect(&m_rcDragItem, FALSE); + + // Dragging around channel headers? Update move indicator... + if((m_nDropItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) InvalidateRect(&m_rcDropItem, FALSE); + if((oldDropItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) InvalidateRect(&oldDropRect, FALSE); + UpdateWindow(); } } + if ((m_dwStatus & PATSTATUS_SELECTROW) /*&& (point.x < m_szHeader.cx)*/ && (point.y > m_szHeader.cy)) { // Mark row number => mark whole row (continue) @@ -2716,7 +2791,6 @@ if(nNumChnNew == vecChns.size()) { pModDoc->SetModified(); - pModDoc->GetPatternUndo()->ClearUndo(); pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); SetCurrentPattern(m_nPattern); Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2011-04-11 19:53:15 UTC (rev 847) +++ trunk/OpenMPT/mptrack/View_pat.h 2011-04-12 21:46:10 UTC (rev 848) @@ -9,6 +9,7 @@ class COpenGLEditor; // Drag & Drop info +#define DRAGITEM_VALUEMASK 0x00FFFF #define DRAGITEM_MASK 0xFF0000 #define DRAGITEM_CHNHEADER 0x010000 #define DRAGITEM_PATTERNHEADER 0x020000 @@ -102,9 +103,14 @@ UINT m_nPattern, m_nRow, m_nMidRow, m_nPlayPat, m_nPlayRow, m_nSpacing, m_nAccelChar, m_nLastPlayedRow, m_nLastPlayedOrder; int m_nXScroll, m_nYScroll; - DWORD m_nDragItem, m_nMenuParam, m_nDetailLevel; - bool m_bDragging, m_bInItemRect, m_bContinueSearch, m_bWholePatternFitsOnScreen; - RECT m_rcDragItem; + DWORD m_nMenuParam, m_nDetailLevel; + + DWORD m_nDragItem; // Currently dragged item + DWORD m_nDropItem; // Currently hovered item during dragondrop + bool m_bDragging, m_bInItemRect, m_bShiftDragging; + RECT m_rcDragItem, m_rcDropItem; + + bool m_bContinueSearch, m_bWholePatternFitsOnScreen; DWORD m_dwStatus, m_dwCursor; DWORD m_dwBeginSel, m_dwEndSel; // Upper-left / Lower-right corners of selection DWORD m_dwStartSel, m_dwDragPos; // Point where selection was started Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-11 19:53:15 UTC (rev 847) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-12 21:46:10 UTC (rev 848) @@ -1523,11 +1523,25 @@ return 0; } + CModDoc *pModDoc = GetpModDoc(); + bool first = true; + if(pModDoc != nullptr && nRemainingChannels != GetNumChannels()) + { + // For now, changing number of channels can't be undone + pModDoc->GetPatternUndo()->ClearUndo(); + } + BEGIN_CRITICAL(); for (PATTERNINDEX nPat = 0; nPat < Patterns.Size(); nPat++) { if (Patterns[nPat]) { + if(pModDoc != nullptr && nRemainingChannels == GetNumChannels()) + { + pModDoc->GetPatternUndo()->PrepareUndo(nPat, 0, 0, GetNumChannels(), Patterns[nPat].GetNumRows(), !first); + first = false; + } + MODCOMMAND *p = Patterns[nPat]; MODCOMMAND *newp = CPattern::AllocatePattern(Patterns[nPat].GetNumRows(), nRemainingChannels); if (!newp) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-12 23:03:47
|
Revision: 849 http://modplug.svn.sourceforge.net/modplug/?rev=849&view=rev Author: saga-games Date: 2011-04-12 23:03:37 +0000 (Tue, 12 Apr 2011) Log Message: ----------- [Mod] Improved DMF loader a bit more. [Mod] Updated History.txt Modified Paths: -------------- trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/soundlib/LOAD_DMF.CPP Modified: trunk/OpenMPT/packageTemplate/History.txt =================================================================== --- trunk/OpenMPT/packageTemplate/History.txt 2011-04-12 21:46:10 UTC (rev 848) +++ trunk/OpenMPT/packageTemplate/History.txt 2011-04-12 23:03:37 UTC (rev 849) @@ -10,6 +10,32 @@ (tx XYZ): thanks to XYZ for telling us about the bug / requesting the feature +v1.19.02.00 (***** 2011, revision 848) +-------------------------------------- +Pattern tab::Note properties + [New] <Jojo> Channels can now be moved by dragging their channel header. Holding Shift while doing so duplicates the channel + [Imp] <Jojo> Moving channels through the channel manager creates an undo point now. + [Fix] <Jojo> Axx is not limited to value 7F anymore in IT / S3M format. + +VST + [New] <Jojo> New menu entry in the plugin editor: Create instrument from plugin + [Fix] <Jojo> Fixed note handling in VST editor of plugins that actually don't support MIDI input (http://bugs.openmpt.org/view.php?id=102) + +Mod Conversion + [Imp] <Jojo> Improved conversion of Sxx (IT / S3M) and PC Notes. + [Fix] <Jojo> Sustain loop conversion didn't work + +IT + [Fix] <Jojo> Panning slides with both parameter nibbles set were not ignored in compatible mode. + +Other modules + [Imp] <Jojo> DMF Loader was rewritten completely and is a whole lot more accurate now. + [Fix] <Jojo> J2B Loader: Empty sample slots are now treated correct in new J2B (AM) files. + +Misc + [New] <Jojo> OpenMPT can now automatically check for updates (daily / weekly / monthly) + [Reg] <Jojo> Removed hidden INI flag to suppress warnings when encountering keymaps with unknown items. This option was introduced when faulty keymaps threw multiple message boxes, but now it's just one and it shouldn't be ignored... + v1.19.01.00 (April 2011, revision 836) -------------------------------------- Pattern tab @@ -33,7 +59,7 @@ [Reg] <Jojo> The "Position aware timer" option is gone. The position aware timer is now automatically used. It was optional in the first place because of some buggy code, which is now fixed. Pattern tab::Note properties - [Fix] <Jojo> The meaning of Q0x was displayed wrong for S3M / IT. + [Fix] <Jojo> The meaning of Q0x was displayed wrong for IT / S3M. [Fix] <Jojo> Changing a value didn't create an undo point. (http://bugs.openmpt.org/view.php?id=56) [Fix] <Jojo> Setting the PC note plugin didn't work. @@ -71,7 +97,6 @@ VST [New] <Jojo> Plugins can now request common file dialogs (file and directory selection). - [New] <Jojo> New menu entry in the plugin editor: Create instrument from plugin [Mod] <Jojo> When automatically inserting a new instrument from the VST editor, the bank and patch values are now not filled in anymore, so it is easier to change to another patch while editing. [Mod] <Jojo> Various small improvements to support VST 2.4 plugins better. [Fix] <Jojo> Speaker arrangement is now sent to the plugins upon initialization. This fixes Voxengo SPAN 2 (a VST 2.4 plugin). Does this break other multichannel plugins? Modified: trunk/OpenMPT/soundlib/LOAD_DMF.CPP =================================================================== --- trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-12 21:46:10 UTC (rev 848) +++ trunk/OpenMPT/soundlib/LOAD_DMF.CPP 2011-04-12 23:03:37 UTC (rev 849) @@ -28,6 +28,7 @@ #define DMF_SMPD 0x44504D53 #define DMF_SMPJ 0x4A504D53 #define DMF_ENDE 0x45444E45 +#define DMF_SETT 0x9C219DE4 // Pattern flags - global track #define DMFPAT_GLOBPACK 0x80 // Pack information for global track follows @@ -150,7 +151,7 @@ val = max(1, val / 4); const bool isFine = (val < 0x0F) || (internalTicks < 2); if(!isFine) - val = max(1, (val + 3) / (internalTicks - 1)); // no slides on first tick! +3 for rounding precision + val = max(1, (val + internalTicks - 2) / (internalTicks - 1)); // no slides on first tick! "+ internalTicks - 2" for rounding precision if(up) return (isFine ? 0x0F : 0x00) | (val << 4); @@ -176,8 +177,9 @@ uint8 DMFdelay2MPT(uint8 val, const uint8 internalTicks) //------------------------------------------------------ { - const int newval = (int)val * (int)internalTicks / 255; - return (uint8)CLAMP(newval, 0, 0x0F); + int newval = (int)val * (int)internalTicks / 255; + Limit(newval, 0, 15); + return (uint8)newval; } @@ -351,7 +353,7 @@ break; } } - tempo = CLAMP(tempo, 32, 255); + Limit(tempo, 32, 255); settings.internalTicks = (uint8)speed; } else { @@ -359,7 +361,7 @@ } } - MODCOMMAND *m = pSndFile->Patterns[nPat].GetpModCommand(nRow, 1); // Reserve first channel for global effects + m = pSndFile->Patterns[nPat].GetpModCommand(nRow, 1); // Reserve first channel for global effects for(CHANNELINDEX nChn = 1; nChn <= numChannels; nChn++, m++) { @@ -368,6 +370,7 @@ { ASSERT_CAN_READ_PATTERN(1); const uint8 channelInfo = lpStream[dwMemPos++]; + //////////////////////////////////////////////////////////////// // 0x80: Packing counter (if not present, counter stays at 0) if((channelInfo & DMFPAT_COUNTER) != 0) { @@ -375,6 +378,7 @@ channelCounter[nChn] = lpStream[dwMemPos++]; } + //////////////////////////////////////////////////////////////// // 0x40: Instrument bool slideNote = true; // If there is no instrument number next to a note, the note is not retriggered! if((channelInfo & DMFPAT_INSTR) != 0) @@ -387,6 +391,7 @@ } } + //////////////////////////////////////////////////////////////// // 0x20: Note if((channelInfo & DMFPAT_NOTE) != 0) { @@ -394,12 +399,13 @@ m->note = lpStream[dwMemPos++]; if(m->note >= 1 && m->note <= 108) { - m->note += 24; + m->note = CLAMP(m->note + 24, NOTE_MIN, NOTE_MAX); settings.lastNote[nChn] = m->note; } else if(m->note >= 129 && m->note <= 236) { // "Buffer notes" for portamento (and other effects?) that are actually not played, but just "queued"... - settings.noteBuffer[nChn] = (m->note & 0x7F) + 24; + m->note = CLAMP((m->note & 0x7F) + 24, NOTE_MIN, NOTE_MAX); + settings.noteBuffer[nChn] = m->note; m->note = NOTE_NONE; } else if(m->note == 255) { @@ -422,6 +428,7 @@ uint8 effect1 = CMD_NONE, effect2 = CMD_NONE, effect3 = CMD_NONE; uint8 effectParam1 = 0, effectParam2 = 0, effectParam3 = 0; + //////////////////////////////////////////////////////////////// // 0x10: Volume if((channelInfo & DMFPAT_VOLUME) != 0) { @@ -430,6 +437,7 @@ m->vol = (lpStream[dwMemPos++] + 3) / 4; } + //////////////////////////////////////////////////////////////// // 0x08: Instrument effect if((channelInfo & DMFPAT_INSEFF) != 0) { @@ -499,6 +507,7 @@ } } + //////////////////////////////////////////////////////////////// // 0x04: Note effect if((channelInfo & DMFPAT_NOTEEFF) != 0) { @@ -541,7 +550,7 @@ effect2 = CMD_TONEPORTAMENTO; break; case 7: // Scratch to Note (neat! but we don't have such an effect...) - m->note = effectParam2 + 25; + m->note = CLAMP(effectParam2 + 25, NOTE_MIN, NOTE_MAX); effect2 = CMD_TONEPORTAMENTO; effectParam2 = 0xFF; break; @@ -578,6 +587,7 @@ } } + //////////////////////////////////////////////////////////////// // 0x02: Volume effect if((channelInfo & DMFPAT_VOLEFF) != 0) { @@ -957,16 +967,16 @@ break; case DMF_SMPJ: // "SMPJ" - Sample jump points (xtracker32 only) + case DMF_SETT: // "Unprintable ID" - those might be GUI settings and other related stuff break; -#if 0 +#ifdef DEBUG default: - // There is some (encrypted?) IFF chunk with a very weird ID at the end of many DMF files. What does it mean? { - char s[32]; + char s[40]; const char *sig = (char *)&chunkheader.signature; - wsprintf(s, "Unknown chunk ID %c%c%c%c at %d", sig[0], sig[1], sig[2], sig[3], dwMemPos - sizeof(DMF_IFFCHUNK)); - MessageBox(0, s, 0, 0); + wsprintf(s, "Unknown chunk ID %c%c%c%c at %d\n", sig[0], sig[1], sig[2], sig[3], dwMemPos - sizeof(DMF_IFFCHUNK)); + if(GetpModDoc()) GetpModDoc()->AddToLog(s); } #endif } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-13 13:45:01
|
Revision: 851 http://modplug.svn.sourceforge.net/modplug/?rev=851&view=rev Author: saga-games Date: 2011-04-13 13:44:49 +0000 (Wed, 13 Apr 2011) Log Message: ----------- A whole ton of refacting! - ReArrangeChannels and MoveChannel have been moved to CModDoc - Many channel adding/removing functions have been rewritten to use ReArrangeChannels, to avoid all this mess of copypasta - Related changes to code and semantics (ReArrangeChannels returns CHANNELINDEX_INVALID on failure, changed CheckUnusedChannels() to CheckUsedChannels(), replaced big arrays with vectors, etc...) Modified Paths: -------------- trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/mptrack/test/test.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp =================================================================== --- trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/ChannelManagerDlg.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -200,11 +200,11 @@ { newChnOrder.push_back(newpat[nChn]); } - if(m_pSndFile->ReArrangeChannels(newChnOrder) != nChannels) + if(pModDoc->ReArrangeChannels(newChnOrder) != nChannels) { - MessageBox("Rearranging channels failed"); END_CRITICAL(); EndWaitCursor(); + MessageBox("Rearranging channels failed"); ResetState(true, true, true, true, true); LeaveCriticalSection(&applying); Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -1491,7 +1491,7 @@ int nRenderPasses = 1; // Channel mode - bool unusedChannels[MAX_BASECHANNELS]; + vector<bool> usedChannels; vector<DWORD> channelFlags; // Instrument mode vector<bool> instrMuteState; @@ -1500,8 +1500,7 @@ if(wsdlg.m_bChannelMode) { // Don't save empty channels - memset(unusedChannels, false, sizeof(unusedChannels)); - CheckUnusedChannels(unusedChannels); + CheckUsedChannels(usedChannels); nRenderPasses = m_SndFile.GetNumChannels(); channelFlags.resize(nRenderPasses, 0); @@ -1510,7 +1509,7 @@ // Save channels' flags channelFlags[i] = m_SndFile.ChnSettings[i].dwFlags; // Ignore muted channels - if(channelFlags[i] & CHN_MUTE) unusedChannels[i] = true; + if(channelFlags[i] & CHN_MUTE) usedChannels[i] = false; // Mute each channel m_SndFile.ChnSettings[i].dwFlags |= CHN_MUTE; } @@ -1559,7 +1558,7 @@ if(i > 0) m_SndFile.ChnSettings[i - 1].dwFlags |= CHN_MUTE; // Was this channel actually muted? Don't process it then. - if(unusedChannels[i] == true) + if(usedChannels[i] == false) continue; // Add channel number & name (if available) to path string if(strlen(m_SndFile.ChnSettings[i].szName) > 0) Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/Moddoc.h 2011-04-13 13:44:49 UTC (rev 851) @@ -274,8 +274,13 @@ // operations public: bool ChangeModType(MODTYPE wType); - bool ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg = true); + bool ChangeNumChannels(CHANNELINDEX nNewChannels, const bool showCancelInRemoveDlg = true); + CHANNELINDEX ReArrangeChannels(const vector<CHANNELINDEX> &fromToArray); + bool MoveChannel(CHANNELINDEX chn_from, CHANNELINDEX chn_to); + bool RemoveChannels(const vector<bool> &keepMask); + void CheckUsedChannels(vector<bool> &usedMask, CHANNELINDEX maxRemoveCount = MAX_BASECHANNELS) const; + bool ConvertInstrumentsToSamples(); UINT RemovePlugs(const bool (&keepMask)[MAX_MIXPLUGINS]); @@ -342,8 +347,6 @@ void LearnMacro(int macro, long param); void SetElapsedTime(ORDERINDEX nOrd, ROWINDEX nRow); - bool RemoveChannels(bool bChnMask[MAX_BASECHANNELS]); - bool RestartPosToPattern(); bool HasMPTHacks(const bool autofix = false); @@ -373,8 +376,6 @@ BOOL InitializeMod(); void* GetChildFrame(); //rewbs.customKeys - void CheckUnusedChannels(bool mask[MAX_BASECHANNELS], CHANNELINDEX maxRemoveCount = MAX_BASECHANNELS) const; - // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CModDoc) Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -32,156 +32,267 @@ } -// Change the number of channels -bool CModDoc::ChangeNumChannels(UINT nNewChannels, const bool showCancelInRemoveDlg) -//---------------------------------------------------------------------------------- +// Change the number of channels. +// Return true on success. +bool CModDoc::ChangeNumChannels(CHANNELINDEX nNewChannels, const bool showCancelInRemoveDlg) +//------------------------------------------------------------------------------------------ { const CHANNELINDEX maxChans = m_SndFile.GetModSpecifications().channelsMax; - if (nNewChannels > maxChans) { + if (nNewChannels > maxChans) + { CString error; error.Format("Error: Max number of channels for this file type is %d", maxChans); ::AfxMessageBox(error, MB_OK|MB_ICONEXCLAMATION); return false; } - if (nNewChannels == m_SndFile.m_nChannels) return false; - if (nNewChannels < m_SndFile.m_nChannels) + if (nNewChannels == GetNumChannels()) return false; + + if (nNewChannels < GetNumChannels()) { + // Remove channels UINT nChnToRemove = 0; CHANNELINDEX nFound = 0; //nNewChannels = 0 means user can choose how many channels to remove - if(nNewChannels > 0) { - nChnToRemove = m_SndFile.m_nChannels - nNewChannels; + if(nNewChannels > 0) + { + nChnToRemove = GetNumChannels() - nNewChannels; nFound = nChnToRemove; - } else { + } else + { nChnToRemove = 0; - nFound = m_SndFile.m_nChannels; + nFound = GetNumChannels(); } CRemoveChannelsDlg rem(&m_SndFile, nChnToRemove, showCancelInRemoveDlg); - CheckUnusedChannels(rem.m_bChnMask, nFound); + CheckUsedChannels(rem.m_bKeepMask, nFound); if (rem.DoModal() != IDOK) return false; // Removing selected channels - RemoveChannels(rem.m_bChnMask); + return RemoveChannels(rem.m_bKeepMask); } else { + // Increasing number of channels BeginWaitCursor(); - // Increasing number of channels - BEGIN_CRITICAL(); - for (UINT i=0; i<m_SndFile.Patterns.Size(); i++) if (m_SndFile.Patterns[i]) + vector<CHANNELINDEX> channels(nNewChannels, CHANNELINDEX_INVALID); + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) { - MODCOMMAND *p = m_SndFile.Patterns[i]; - MODCOMMAND *newp = CPattern::AllocatePattern(m_SndFile.Patterns[i].GetNumRows(), nNewChannels); - if (!newp) - { - END_CRITICAL(); - AddToLog("ERROR: Not enough memory to create new channels!\nPattern Data is corrupted!\n"); - return false; - } - for (UINT j=0; j<m_SndFile.Patterns[i].GetNumRows(); j++) - { - memcpy(&newp[j*nNewChannels], &p[j*m_SndFile.m_nChannels], m_SndFile.m_nChannels*sizeof(MODCOMMAND)); - } - m_SndFile.Patterns[i] = newp; - CPattern::FreePattern(p); + channels[nChn] = nChn; } - //if channel was removed before and is added again, mute status has to be unset! (bug 1814) - for (UINT i=m_SndFile.m_nChannels; i<nNewChannels; i++) + const bool success = (ReArrangeChannels(channels) == nNewChannels); + if(success) { - m_SndFile.InitChannel(i); + SetModified(); + UpdateAllViews(NULL, HINT_MODTYPE); } - - m_SndFile.m_nChannels = nNewChannels; - m_SndFile.SetupMODPanning(); - END_CRITICAL(); - EndWaitCursor(); + return success; } - SetModified(); - GetPatternUndo()->ClearUndo(); - UpdateAllViews(NULL, HINT_MODTYPE); - return true; } -bool CModDoc::RemoveChannels(bool m_bChnMask[MAX_BASECHANNELS]) -//--------------------------------------------------------- -//To remove all channels whose index corresponds to true value at m_bChnMask[] array. Code is almost non-modified copy of -//the code which was in CModDoc::ChangeNumChannels(UINT nNewChannels) - the only differences are the lines before -//BeginWaitCursor(), few lines in the end and that nNewChannels is renamed to nRemaningChannels. +// To remove all channels whose index corresponds to false in the keepMask vector. +// Return true on success. +bool CModDoc::RemoveChannels(const vector<bool> &keepMask) +//-------------------------------------------------------- { - UINT nRemainingChannels = 0; - //First calculating how many channels are to be left - UINT i = 0; - for(i = 0; i<m_SndFile.m_nChannels; i++) + UINT nRemainingChannels = 0; + //First calculating how many channels are to be left + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) + { + if(keepMask[nChn]) nRemainingChannels++; + } + if(nRemainingChannels == GetNumChannels() || nRemainingChannels < m_SndFile.GetModSpecifications().channelsMin) + { + CString str; + if(nRemainingChannels == GetNumChannels()) str.Format("No channels chosen to be removed."); + else str.Format("No removal done - channel number is already at minimum."); + CMainFrame::GetMainFrame()->MessageBox(str, "Remove channel", MB_OK | MB_ICONINFORMATION); + return false; + } + + BeginWaitCursor(); + // Create new channel order, with only channels from m_bChnMask left. + vector<CHANNELINDEX> channels(nRemainingChannels, 0); + CHANNELINDEX i = 0; + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) + { + if(keepMask[nChn]) { - if(!m_bChnMask[i]) nRemainingChannels++; + channels[i++] = nChn; } - if(nRemainingChannels == m_SndFile.m_nChannels || nRemainingChannels < m_SndFile.GetModSpecifications().channelsMin) - { - CString str; - if(nRemainingChannels == m_SndFile.m_nChannels) str.Format("No channels chosen to be removed."); - else str.Format("No removal done - channel number is already at minimum."); - CMainFrame::GetMainFrame()->MessageBox(str , "Remove channel", MB_OK | MB_ICONINFORMATION); - return false; - } + } + const bool success = (ReArrangeChannels(channels) == nRemainingChannels); + if(success) + { + SetModified(); + UpdateAllViews(NULL, HINT_MODTYPE); + } + EndWaitCursor(); + return success; - BeginWaitCursor(); - BEGIN_CRITICAL(); - for (i=0; i<m_SndFile.Patterns.Size(); i++) if (m_SndFile.Patterns[i]) +} + + +// Base code for adding, removing, moving and duplicating channels. Returns new number of channels on success, CHANNELINDEX_INVALID otherwise. +// The new channel vector can contain CHANNELINDEX_INVALID for adding new (empty) channels. +CHANNELINDEX CModDoc::ReArrangeChannels(const vector<CHANNELINDEX> &newOrder) +//--------------------------------------------------------------------------- +{ + //newOrder[i] tells which current channel should be placed to i:th position in + //the new order, or if i is not an index of current channels, then new channel is + //added to position i. If index of some current channel is missing from the + //newOrder-vector, then the channel gets removed. + + const CHANNELINDEX nRemainingChannels = static_cast<CHANNELINDEX>(newOrder.size()); + + if(nRemainingChannels > m_SndFile.GetModSpecifications().channelsMax || nRemainingChannels < m_SndFile.GetModSpecifications().channelsMin) + { + CString str; + str.Format(GetStrI18N(_TEXT("Can't apply change: Number of channels should be within [%u,%u]")), m_SndFile.GetModSpecifications().channelsMin, m_SndFile.GetModSpecifications().channelsMax); + CMainFrame::GetMainFrame()->MessageBox(str , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); + return CHANNELINDEX_INVALID; + } + + bool first = true; + if(nRemainingChannels != GetNumChannels()) + { + // For now, changing number of channels can't be undone + GetPatternUndo()->ClearUndo(); + } + + BEGIN_CRITICAL(); + for(PATTERNINDEX nPat = 0; nPat < m_SndFile.Patterns.Size(); nPat++) + { + if(m_SndFile.Patterns[nPat]) { - MODCOMMAND *p = m_SndFile.Patterns[i]; - MODCOMMAND *newp = CPattern::AllocatePattern(m_SndFile.Patterns[i].GetNumRows(), nRemainingChannels); - if (!newp) + if(nRemainingChannels == GetNumChannels()) { + GetPatternUndo()->PrepareUndo(nPat, 0, 0, GetNumChannels(), m_SndFile.Patterns[nPat].GetNumRows(), !first); + first = false; + } + + MODCOMMAND *p = m_SndFile.Patterns[nPat]; + MODCOMMAND *newp = CPattern::AllocatePattern(m_SndFile.Patterns[nPat].GetNumRows(), nRemainingChannels); + if(!newp) + { END_CRITICAL(); - AddToLog("ERROR: Not enough memory to resize patterns!\nPattern Data is corrupted!"); - return true; + CMainFrame::GetMainFrame()->MessageBox("ERROR: Pattern allocation failed in ReArrangechannels(...)" , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); + return CHANNELINDEX_INVALID; } MODCOMMAND *tmpsrc = p, *tmpdest = newp; - for (UINT j=0; j<m_SndFile.Patterns[i].GetNumRows(); j++) + for(ROWINDEX nRow = 0; nRow < m_SndFile.Patterns[nPat].GetNumRows(); nRow++) //Scrolling rows { - for (UINT k=0; k<m_SndFile.m_nChannels; k++, tmpsrc++) + for(CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++, tmpdest++) //Scrolling channels. { - if (!m_bChnMask[k]) *tmpdest++ = *tmpsrc; + if(newOrder[nChn] < GetNumChannels()) //Case: getting old channel to the new channel order. + *tmpdest = tmpsrc[nRow * GetNumChannels() + newOrder[nChn]]; + else //Case: figure newOrder[k] is not the index of any current channel, so adding a new channel. + *tmpdest = MODCOMMAND::Empty(); + } } - m_SndFile.Patterns[i] = newp; + m_SndFile.Patterns[nPat] = newp; CPattern::FreePattern(p); } - UINT tmpchn = 0; - for (i=0; i<m_SndFile.m_nChannels; i++) + } + + MODCHANNEL chns[MAX_BASECHANNELS]; + MODCHANNELSETTINGS settings[MAX_BASECHANNELS]; + vector<UINT> recordStates(GetNumChannels(), 0); + vector<bool> chnMutePendings(GetNumChannels(), false); + + for(CHANNELINDEX nChn = 0; nChn < GetNumChannels(); nChn++) + { + settings[nChn] = m_SndFile.ChnSettings[nChn]; + chns[nChn] = m_SndFile.Chn[nChn]; + recordStates[nChn] = IsChannelRecord(nChn); + chnMutePendings[nChn] = m_SndFile.m_bChannelMuteTogglePending[nChn]; + } + + ReinitRecordState(); + + for(CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++) + { + if(newOrder[nChn] < GetNumChannels()) { - if (!m_bChnMask[i]) - { - if (tmpchn != i) - { - m_SndFile.ChnSettings[tmpchn] = m_SndFile.ChnSettings[i]; - m_SndFile.Chn[tmpchn] = m_SndFile.Chn[i]; - } - tmpchn++; - } else - { - if (i >= nRemainingChannels) - { - m_SndFile.InitChannel(i); - m_SndFile.Chn[i].dwFlags |= CHN_MUTE; - } - } + m_SndFile.ChnSettings[nChn] = settings[newOrder[nChn]]; + m_SndFile.Chn[nChn] = chns[newOrder[nChn]]; + if(recordStates[newOrder[nChn]] == 1) Record1Channel(nChn, true); + if(recordStates[newOrder[nChn]] == 2) Record2Channel(nChn, true); + m_SndFile.m_bChannelMuteTogglePending[nChn] = chnMutePendings[newOrder[nChn]]; } - m_SndFile.m_nChannels = nRemainingChannels; - END_CRITICAL(); - EndWaitCursor(); - SetModified(); - GetPatternUndo()->ClearUndo(); - UpdateAllViews(NULL, HINT_MODTYPE); - return false; + else + { + m_SndFile.InitChannel(nChn); + } + } + // Reset MOD panning (won't affect other module formats) + m_SndFile.SetupMODPanning(); + + m_SndFile.m_nChannels = nRemainingChannels; + + // Reset removed channels. Most notably, clear the channel name. + for(CHANNELINDEX nChn = GetNumChannels(); nChn < MAX_BASECHANNELS; nChn++) + { + m_SndFile.InitChannel(nChn); + m_SndFile.Chn[nChn].dwFlags |= CHN_MUTE; + } + + END_CRITICAL(); + + return GetNumChannels(); } +bool CModDoc::MoveChannel(CHANNELINDEX chnFrom, CHANNELINDEX chnTo) +//----------------------------------------------------------------- +{ + //Implementation of move channel using ReArrangeChannels(...). So this function + //only creates correct newOrder-vector used in the ReArrangeChannels(...). + if(chnFrom == chnTo) return false; + if(chnFrom >= GetNumChannels() || chnTo >= GetNumChannels()) + { + CString str = "Error: Bad move indexes in CSoundFile::MoveChannel(...)"; + CMainFrame::GetMainFrame()->MessageBox(str , "MoveChannel(...)", MB_OK | MB_ICONINFORMATION); + return true; + } + vector<CHANNELINDEX> newOrder; + //First creating new order identical to current order... + for(CHANNELINDEX i = 0; i < GetNumChannels(); i++) + { + newOrder.push_back(i); + } + //...and then add the move channel effect. + if(chnFrom < chnTo) + { + CHANNELINDEX temp = newOrder[chnFrom]; + for(UINT i = chnFrom; i < chnTo; i++) + { + newOrder[i] = newOrder[i + 1]; + } + newOrder[chnTo] = temp; + } + else //case chnFrom > chnTo(can't be equal, since it has been examined earlier.) + { + CHANNELINDEX temp = newOrder[chnFrom]; + for(UINT i = chnFrom; i >= chnTo + 1; i--) + { + newOrder[i] = newOrder[i - 1]; + } + newOrder[chnTo] = temp; + } + + if(newOrder.size() != ReArrangeChannels(newOrder)) + { + CMainFrame::GetMainFrame()->MessageBox("BUG: Channel number changed in MoveChannel()" , "", MB_OK | MB_ICONINFORMATION); + } + return false; +} + + // Functor for converting instrument numbers to sample numbers in the patterns struct ConvertInstrumentsToSamplesInPatterns //========================================== @@ -1230,15 +1341,16 @@ // Check which channels contain note data. maxRemoveCount specified how many empty channels are reported at max. -void CModDoc::CheckUnusedChannels(bool mask[MAX_BASECHANNELS], CHANNELINDEX maxRemoveCount) const -//----------------------------------------------------------------------------------------------- +void CModDoc::CheckUsedChannels(vector<bool> &usedMask, CHANNELINDEX maxRemoveCount) const +//---------------------------------------------------------------------------------------- { // Checking for unused channels - const int nChannels = m_SndFile.GetNumChannels(); + const int nChannels = GetNumChannels(); + usedMask.resize(nChannels); for(int iRst = nChannels - 1; iRst >= 0; iRst--) { - mask[iRst] = IsChannelUnused(iRst); - if(mask[iRst]) + usedMask[iRst] = !IsChannelUnused(iRst); + if(!usedMask[iRst]) { // Found enough empty channels yet? if((--maxRemoveCount) == 0) break; @@ -1251,7 +1363,7 @@ bool CModDoc::IsChannelUnused(CHANNELINDEX nChn) const //---------------------------------------------------- { - const CHANNELINDEX nChannels = m_SndFile.GetNumChannels(); + const CHANNELINDEX nChannels = GetNumChannels(); if(nChn >= nChannels) { return true; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -1127,8 +1127,6 @@ const bool bItemSelected = m_bInItemRect || ((m_nDragItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER); if (/*(!m_bDragging) ||*/ (!pModDoc)) return; - CSoundFile *pSndFile = pModDoc->GetSoundFile(); - m_bDragging = false; m_bInItemRect = false; ReleaseCapture(); @@ -1187,18 +1185,18 @@ pModDoc->MuteChannel(nItemNo, !pModDoc->IsChannelMuted(nItemNo)); pModDoc->UpdateAllViews(this, HINT_MODCHANNELS | ((nItemNo / CHANNELS_IN_TAB) << HINT_SHIFT_CHNTAB)); } - } else if(nTargetNo < pSndFile->GetNumChannels()) + } else if(nTargetNo < pModDoc->GetNumChannels()) { // Dragged to other channel header => move or copy channel InvalidateRect(&m_rcDropItem, FALSE); const bool duplicate = (nFlags & MK_SHIFT) ? true : false; - vector<CHANNELINDEX> channels(pSndFile->GetNumChannels() + (duplicate ? 1 : 0), 0); + vector<CHANNELINDEX> channels(pModDoc->GetNumChannels() + (duplicate ? 1 : 0), 0); CHANNELINDEX i = 0; bool modified = duplicate; - for(CHANNELINDEX nChn = 0; nChn < pSndFile->GetNumChannels(); nChn++) + for(CHANNELINDEX nChn = 0; nChn < pModDoc->GetNumChannels(); nChn++) { if(nChn == nTargetNo) { @@ -1217,7 +1215,7 @@ modified = true; } } - if(modified && pSndFile->ReArrangeChannels(channels) != 0) + if(modified && pModDoc->ReArrangeChannels(channels) != CHANNELINDEX_INVALID) { if(duplicate) { @@ -2671,15 +2669,17 @@ SetSelectionInstrument(GetCurrentInstrument()); } + void CViewPattern::OnRemoveChannelDialog() //---------------------------------------- { CModDoc *pModDoc = GetDocument(); - if(pModDoc == 0) return; + if(pModDoc == nullptr) return; pModDoc->ChangeNumChannels(0); SetCurrentPattern(m_nPattern); //Updating the screen. } + void CViewPattern::OnRemoveChannel() //---------------------------------- { @@ -2700,33 +2700,35 @@ str.Format("Remove channel %d? This channel still contains note data!\nNote: Operation affects all patterns and has no undo", nChn + 1); if(isEmpty || CMainFrame::GetMainFrame()->MessageBox(str , "Remove channel", MB_YESNO | MB_ICONQUESTION) == IDYES) { - bool chnMask[MAX_BASECHANNELS]; - for(CHANNELINDEX i = 0; i < MAX_BASECHANNELS; i++) {chnMask[i] = false;} - chnMask[nChn] = TRUE; - pModDoc->RemoveChannels(chnMask); + vector<bool> keepMask(pModDoc->GetNumChannels(), true); + keepMask[nChn] = false; + pModDoc->RemoveChannels(keepMask); SetCurrentPattern(m_nPattern); //Updating the screen. } } -void CViewPattern::OnAddChannelFront() -//------------------------------------ +void CViewPattern::AddChannelBefore(CHANNELINDEX nBefore) +//------------------------------------------------------- { - UINT nChn = GetChanFromCursor(m_nMenuParam); CModDoc *pModDoc = GetDocument(); - CSoundFile* pSndFile; - if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) return; + if(pModDoc == nullptr) return; BeginWaitCursor(); - //First adding channel as the last channel... - if (pModDoc->ChangeNumChannels(pSndFile->m_nChannels + 1)) + // Create new channel order, with channel nBefore being an invalid (and thus empty) channel. + vector<CHANNELINDEX> channels(pModDoc->GetNumChannels() + 1, CHANNELINDEX_INVALID); + CHANNELINDEX i = 0; + for(CHANNELINDEX nChn = 0; nChn < pModDoc->GetNumChannels() + 1; nChn++) { - pSndFile->InitChannel(pSndFile->m_nChannels-1); - //...and then moving it to right position. - pSndFile->MoveChannel(pSndFile->m_nChannels-1, nChn); + if(nChn != nBefore) + { + channels[nChn] = i++; + } + } + if (pModDoc->ReArrangeChannels(channels) != CHANNELINDEX_INVALID) + { pModDoc->SetModified(); - pModDoc->GetPatternUndo()->ClearUndo(); pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); //refresh channel headers pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); //updates(?) the channel number to general tab display SetCurrentPattern(m_nPattern); @@ -2735,70 +2737,45 @@ } -void CViewPattern::OnAddChannelAfter() -//------------------------------------ -{ - UINT nChn = ((m_nMenuParam&0xFFFF)>>3)+1; - CModDoc *pModDoc = GetDocument(); - CSoundFile* pSndFile; - if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) return; - - BeginWaitCursor(); - if (pModDoc->ChangeNumChannels(pSndFile->m_nChannels + 1)) - { - pSndFile->InitChannel(pSndFile->m_nChannels-1); - pSndFile->MoveChannel(pSndFile->m_nChannels-1, nChn); - - pModDoc->SetModified(); - pModDoc->GetPatternUndo()->ClearUndo(); - pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); - pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); - SetCurrentPattern(m_nPattern); - } - EndWaitCursor(); -} - void CViewPattern::OnDuplicateChannel() //------------------------------------ { CModDoc *pModDoc = GetDocument(); - CSoundFile* pSndFile; - if (pModDoc == 0 || (pSndFile = pModDoc->GetSoundFile()) == 0) - return; + if (pModDoc == nullptr) return; if(AfxMessageBox(GetStrI18N(_TEXT("This affects all patterns, proceed?")), MB_YESNO) != IDYES) return; const CHANNELINDEX nDupChn = GetChanFromCursor(m_nMenuParam); - if(nDupChn >= pSndFile->GetNumChannels()) + if(nDupChn >= pModDoc->GetNumChannels()) return; - CHANNELINDEX nNumChnNew = pSndFile->GetNumChannels()+1; - // Create vector {0, 1,..., n-1, n, n, n+1, n+2, ..., nNumChnNew-2), where n = nDupChn. - vector<CHANNELINDEX> vecChns(nNumChnNew); + BeginWaitCursor(); + // Create new channel order, with channel nDupChn duplicated. + vector<CHANNELINDEX> channels(pModDoc->GetNumChannels() + 1, 0); CHANNELINDEX i = 0; - for(i = 0; i<nDupChn+1; i++) - vecChns[i] = i; - vecChns[i] = nDupChn; - i++; - for(; i<nNumChnNew; i++) - vecChns[i] = i-1; + for(CHANNELINDEX nChn = 0; nChn < pModDoc->GetNumChannels() + 1; nChn++) + { + channels[nChn] = i; + if(nChn != nDupChn) + { + i++; + } + } - nNumChnNew = pSndFile->ReArrangeChannels(vecChns); - // Check that duplication happened and in that case update. - if(nNumChnNew == vecChns.size()) + if(pModDoc->ReArrangeChannels(channels) != CHANNELINDEX_INVALID) { pModDoc->SetModified(); pModDoc->UpdateAllViews(NULL, HINT_MODCHANNELS); pModDoc->UpdateAllViews(NULL, HINT_MODTYPE); SetCurrentPattern(m_nPattern); } - + EndWaitCursor(); } void CViewPattern::OnRunScript() -//-------------------------------- +//------------------------------ { ; } Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/View_pat.h 2011-04-13 13:44:49 UTC (rev 851) @@ -315,8 +315,8 @@ afx_msg void OnTransposeOctUp(); afx_msg void OnTransposeOctDown(); afx_msg void OnSetSelInstrument(); - afx_msg void OnAddChannelFront(); - afx_msg void OnAddChannelAfter(); + afx_msg void OnAddChannelFront() { AddChannelBefore(GetChanFromCursor(m_nMenuParam)); } + afx_msg void OnAddChannelAfter() { AddChannelBefore(GetChanFromCursor(m_nMenuParam) + 1); }; afx_msg void OnDuplicateChannel(); afx_msg void OnRemoveChannel(); afx_msg void OnRemoveChannelDialog(); @@ -406,6 +406,9 @@ // Play one pattern row and stop ("step mode") void PatternStep(bool autoStep); + // Add a channel. + void AddChannelBefore(CHANNELINDEX nBefore); + public: afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point); private: Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -570,7 +570,7 @@ wsprintf(label, "Channel %d", n + 1); m_RemChansList.SetItemData(m_RemChansList.AddString(label), n); - if (m_bChnMask[n]) m_RemChansList.SetSel(n); + if (!m_bKeepMask[n]) m_RemChansList.SetSel(n); } if (m_nRemove > 0) { @@ -590,15 +590,15 @@ void CRemoveChannelsDlg::OnOK() //----------------------------- { - memset(m_bChnMask, false, sizeof(m_bChnMask)); int nCount = m_RemChansList.GetSelCount(); CArray<int,int> aryListBoxSel; aryListBoxSel.SetSize(nCount); m_RemChansList.GetSelItems(nCount, aryListBoxSel.GetData()); - for (int n=0; n<nCount; n++) + m_bKeepMask.assign(m_nChannels, true); + for (int n = 0; n < nCount; n++) { - m_bChnMask[aryListBoxSel[n]] = true; + m_bKeepMask[aryListBoxSel[n]] = false; } if ((static_cast<UINT>(nCount) == m_nRemove && nCount > 0) || (m_nRemove == 0 && (m_pSndFile->GetNumChannels() >= nCount + m_pSndFile->GetModSpecifications().channelsMin))) CDialog::OnOK(); Modified: trunk/OpenMPT/mptrack/dlg_misc.h =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/dlg_misc.h 2011-04-13 13:44:49 UTC (rev 851) @@ -84,17 +84,17 @@ { public: CSoundFile *m_pSndFile; - bool m_bChnMask[MAX_BASECHANNELS]; - UINT m_nChannels, m_nRemove; + vector<bool> m_bKeepMask; + CHANNELINDEX m_nChannels, m_nRemove; CListBox m_RemChansList; //rewbs.removeChansDlgCleanup bool m_ShowCancel; public: - CRemoveChannelsDlg(CSoundFile *pSndFile, UINT nChns, bool showCancel = true, CWnd *parent=NULL):CDialog(IDD_REMOVECHANNELS, parent) + CRemoveChannelsDlg(CSoundFile *pSndFile, CHANNELINDEX nChns, bool showCancel = true, CWnd *parent=NULL):CDialog(IDD_REMOVECHANNELS, parent) { m_pSndFile = pSndFile; - m_nChannels = m_pSndFile->m_nChannels; - m_nRemove = nChns; - memset(m_bChnMask, false, sizeof(m_bChnMask)); + m_nChannels = m_pSndFile->GetNumChannels(); + m_nRemove = nChns; + m_bKeepMask.assign(m_nChannels, true); m_ShowCancel = showCancel; } Modified: trunk/OpenMPT/mptrack/test/test.cpp =================================================================== --- trunk/OpenMPT/mptrack/test/test.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/mptrack/test/test.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -239,16 +239,16 @@ CMainFrame* pMainFrm = CMainFrame::GetMainFrame(); if(pMainFrm == nullptr) throw(std::runtime_error("pMainFrm is nullptr")); - CModDoc* pModdoc = pMainFrm->GetActiveDoc(); - if(pModdoc == nullptr) + CModDoc* pModDoc = pMainFrm->GetActiveDoc(); + if(pModDoc == nullptr) throw(std::runtime_error("pModdoc is nullptr")); - CSoundFile* pSndFile = pModdoc->GetSoundFile(); + CSoundFile* pSndFile = pModDoc->GetSoundFile(); if(pSndFile == nullptr) throw(std::runtime_error("pSndFile is nullptr")); // Set maximum number of channels. - pSndFile->ReArrangeChannels(std::vector<CHANNELINDEX>(ModSpecs::mptm.channelsMax , 0)); + pModDoc->ReArrangeChannels(std::vector<CHANNELINDEX>(ModSpecs::mptm.channelsMax , 0)); pSndFile->Patterns.Remove(0); pSndFile->Patterns.Insert(0, ModSpecs::mptm.patternRowsMin); @@ -305,7 +305,7 @@ VERIFY_EQUAL( bPatternDataMatch, true); } - pModdoc->OnCloseDocument(); + pModDoc->OnCloseDocument(); } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 13:44:49 UTC (rev 851) @@ -1505,166 +1505,6 @@ } -CHANNELINDEX CSoundFile::ReArrangeChannels(const vector<CHANNELINDEX>& newOrder) -//------------------------------------------------------------------------------ -{ - //newOrder[i] tells which current channel should be placed to i:th position in - //the new order, or if i is not an index of current channels, then new channel is - //added to position i. If index of some current channel is missing from the - //newOrder-vector, then the channel gets removed. - - const CHANNELINDEX nRemainingChannels = static_cast<CHANNELINDEX>(newOrder.size()); - - if(nRemainingChannels > GetModSpecifications().channelsMax || nRemainingChannels < GetModSpecifications().channelsMin) - { - CString str; - str.Format(GetStrI18N(_TEXT("Can't apply change: Number of channels should be within [%u,%u]")), GetModSpecifications().channelsMin, GetModSpecifications().channelsMax); - CMainFrame::GetMainFrame()->MessageBox(str , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); - return 0; - } - - CModDoc *pModDoc = GetpModDoc(); - bool first = true; - if(pModDoc != nullptr && nRemainingChannels != GetNumChannels()) - { - // For now, changing number of channels can't be undone - pModDoc->GetPatternUndo()->ClearUndo(); - } - - BEGIN_CRITICAL(); - for (PATTERNINDEX nPat = 0; nPat < Patterns.Size(); nPat++) - { - if (Patterns[nPat]) - { - if(pModDoc != nullptr && nRemainingChannels == GetNumChannels()) - { - pModDoc->GetPatternUndo()->PrepareUndo(nPat, 0, 0, GetNumChannels(), Patterns[nPat].GetNumRows(), !first); - first = false; - } - - MODCOMMAND *p = Patterns[nPat]; - MODCOMMAND *newp = CPattern::AllocatePattern(Patterns[nPat].GetNumRows(), nRemainingChannels); - if (!newp) - { - END_CRITICAL(); - CMainFrame::GetMainFrame()->MessageBox("ERROR: Pattern allocation failed in ReArrangechannels(...)" , "ReArrangeChannels", MB_OK | MB_ICONINFORMATION); - return 0; - } - MODCOMMAND *tmpsrc = p, *tmpdest = newp; - for (ROWINDEX nRow = 0; nRow<Patterns[nPat].GetNumRows(); nRow++) //Scrolling rows - { - for (CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++, tmpdest++) //Scrolling channels. - { - if(newOrder[nChn] < m_nChannels) //Case: getting old channel to the new channel order. - *tmpdest = tmpsrc[nRow*m_nChannels+newOrder[nChn]]; - else //Case: figure newOrder[k] is not the index of any current channel, so adding a new channel. - *tmpdest = MODCOMMAND::Empty(); - - } - } - Patterns[nPat] = newp; - CPattern::FreePattern(p); - } - } - - MODCHANNELSETTINGS settings[MAX_BASECHANNELS]; - MODCHANNEL chns[MAX_BASECHANNELS]; - UINT recordStates[MAX_BASECHANNELS]; - bool chnMutePendings[MAX_BASECHANNELS]; - - for(CHANNELINDEX nChn = 0; nChn < m_nChannels; nChn++) - { - settings[nChn] = ChnSettings[nChn]; - chns[nChn] = Chn[nChn]; - if(m_pModDoc) - recordStates[nChn] = m_pModDoc->IsChannelRecord(nChn); - chnMutePendings[nChn] = m_bChannelMuteTogglePending[nChn]; - } - - if(m_pModDoc) - m_pModDoc->ReinitRecordState(); - - for (CHANNELINDEX nChn = 0; nChn < nRemainingChannels; nChn++) - { - if(newOrder[nChn] < m_nChannels) - { - ChnSettings[nChn] = settings[newOrder[nChn]]; - Chn[nChn] = chns[newOrder[nChn]]; - if(m_pModDoc) - { - if(recordStates[newOrder[nChn]] == 1) m_pModDoc->Record1Channel(nChn, true); - if(recordStates[newOrder[nChn]] == 2) m_pModDoc->Record2Channel(nChn, true); - } - m_bChannelMuteTogglePending[nChn] = chnMutePendings[newOrder[nChn]]; - } - else - { - InitChannel(nChn); - } - } - // Reset MOD panning (won't affect other module formats) - SetupMODPanning(); - - m_nChannels = nRemainingChannels; - - // Reset removed channels. Most notably, clear the channel name. - for(CHANNELINDEX nChn = m_nChannels; nChn < MAX_BASECHANNELS; nChn++) - { - InitChannel(nChn); - Chn[nChn].dwFlags |= CHN_MUTE; - } - - END_CRITICAL(); - - return static_cast<CHANNELINDEX>(m_nChannels); -} - -bool CSoundFile::MoveChannel(UINT chnFrom, UINT chnTo) -//---------------------------------------------------- -{ - //Implementation of move channel using ReArrangeChannels(...). So this function - //only creates correct newOrder-vector used in the ReArrangeChannels(...). - if(chnFrom == chnTo) return false; - if(chnFrom >= m_nChannels || chnTo >= m_nChannels) - { - CString str = "Error: Bad move indexes in CSoundFile::MoveChannel(...)"; - CMainFrame::GetMainFrame()->MessageBox(str , "MoveChannel(...)", MB_OK | MB_ICONINFORMATION); - return true; - } - vector<CHANNELINDEX> newOrder; - //First creating new order identical to current order... - for(CHANNELINDEX i = 0; i<GetNumChannels(); i++) - { - newOrder.push_back(i); - } - //...and then add the move channel effect. - if(chnFrom < chnTo) - { - CHANNELINDEX temp = newOrder[chnFrom]; - for(UINT i = chnFrom; i<chnTo; i++) - { - newOrder[i] = newOrder[i+1]; - } - newOrder[chnTo] = temp; - } - else //case chnFrom > chnTo(can't be equal, since it has been examined earlier.) - { - CHANNELINDEX temp = newOrder[chnFrom]; - for(UINT i = chnFrom; i>=chnTo+1; i--) - { - newOrder[i] = newOrder[i-1]; - } - newOrder[chnTo] = temp; - } - - if(newOrder.size() != ReArrangeChannels(newOrder)) - { - CMainFrame::GetMainFrame()->MessageBox("BUG: Channel number changed in MoveChannel()" , "", MB_OK | MB_ICONINFORMATION); - } - return false; -} - - #ifndef NO_PACKING UINT CSoundFile::PackSample(int &sample, int next) //------------------------------------------------ Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 00:44:30 UTC (rev 850) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 13:44:49 UTC (rev 851) @@ -740,8 +740,6 @@ void CheckCPUUsage(UINT nCPU); BOOL SetPatternName(PATTERNINDEX nPat, LPCSTR lpszName); BOOL GetPatternName(PATTERNINDEX nPat, LPSTR lpszName, UINT cbSize=MAX_PATTERNNAME) const; - CHANNELINDEX ReArrangeChannels(const vector<CHANNELINDEX>& fromToArray); - bool MoveChannel(UINT chn_from, UINT chn_to); void SetupITBidiMode(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-13 17:44:38
|
Revision: 852 http://modplug.svn.sourceforge.net/modplug/?rev=852&view=rev Author: saga-games Date: 2011-04-13 17:44:31 +0000 (Wed, 13 Apr 2011) Log Message: ----------- [Fix] Damn... installer was copying release note images to a wrong directory! [Imp] Update Checker: Update URL can now be reset in the config dialog. [Mod] Mod Conversion: When converting from MOD/S3M to XM/IT, compatible play is automatically enabled. [Ref] More refactoring in view_pat.cpp Modified Paths: -------------- trunk/OpenMPT/installer/install.iss trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/mptrack/UpdateCheck.cpp trunk/OpenMPT/mptrack/UpdateCheck.h trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/mptrack/mptrack.rc Modified: trunk/OpenMPT/installer/install.iss =================================================================== --- trunk/OpenMPT/installer/install.iss 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/installer/install.iss 2011-04-13 17:44:31 UTC (rev 852) @@ -73,7 +73,7 @@ ; release notes Source: ..\packageTemplate\ReleaseNotesImages\general\*.*; DestDir: {app}\ReleaseNotesImages\general\; Flags: ignoreversion sortfilesbyextension -Source: ..\packageTemplate\ReleaseNotesImages\1.19\*.*; DestDir: {app}\ReleaseNotesImages\1.18\; Flags: ignoreversion sortfilesbyextension +Source: ..\packageTemplate\ReleaseNotesImages\1.19\*.*; DestDir: {app}\ReleaseNotesImages\1.19\; Flags: ignoreversion sortfilesbyextension Source: ..\packageTemplate\OMPT_1.19_ReleaseNotes.html; DestDir: {app}; Flags: ignoreversion ; soundtouch license stuff Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2011-04-13 17:44:31 UTC (rev 852) @@ -509,7 +509,7 @@ r.top = rect.top; r.bottom = rect.bottom; // Drop position depends on whether hovered channel is left or right of dragged item. - r.left = ((m_nDropItem & DRAGITEM_VALUEMASK) < (m_nDragItem & DRAGITEM_VALUEMASK) || m_bShiftDragging) ? rect.left : rect.right - 3; + r.left = ((m_nDropItem & DRAGITEM_VALUEMASK) < (m_nDragItem & DRAGITEM_VALUEMASK) || m_bShiftDragging) ? rect.left : rect.right - 2; r.right = r.left + 2; ::FillRect(hdc, &r, CMainFrame::brushText); } Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2011-04-13 17:44:31 UTC (rev 852) @@ -458,6 +458,11 @@ CHANGEMODTYPE_WARNING(wMixmode); } + // Automatically enable compatible mode when converting from MOD and S3M, since it's automatically enabled in those formats. + if((nOldType & (MOD_TYPE_MOD|MOD_TYPE_S3M)) && (nNewType & (MOD_TYPE_XM|MOD_TYPE_IT))) + { + m_SndFile.SetModFlag(MSF_COMPATIBLE_PLAY, true); + } if((nNewType & (MOD_TYPE_XM|MOD_TYPE_IT)) && !m_SndFile.GetModFlag(MSF_COMPATIBLE_PLAY)) { CHANGEMODTYPE_WARNING(wCompatibilityMode); Modified: trunk/OpenMPT/mptrack/UpdateCheck.cpp =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.cpp 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/UpdateCheck.cpp 2011-04-13 17:44:31 UTC (rev 852) @@ -17,10 +17,12 @@ #endif +const CString CUpdateCheck::defaultUpdateURL = "http://update.openmpt.org/check/%s"; + // Static configuration variables time_t CUpdateCheck::lastUpdateCheck = 0; int CUpdateCheck::updateCheckPeriod = 7; -CString CUpdateCheck::updateBaseURL = "http://update.openmpt.org/check/%s"; +CString CUpdateCheck::updateBaseURL = CUpdateCheck::defaultUpdateURL; bool CUpdateCheck::showUpdateHint = true; @@ -271,6 +273,7 @@ BEGIN_MESSAGE_MAP(CUpdateSetupDlg, CPropertyPage) ON_COMMAND(IDC_BUTTON1, OnCheckNow) + ON_COMMAND(IDC_BUTTON2, OnResetURL) ON_COMMAND(IDC_RADIO1, OnSettingsChanged) ON_COMMAND(IDC_RADIO2, OnSettingsChanged) ON_COMMAND(IDC_RADIO3, OnSettingsChanged) @@ -342,3 +345,9 @@ CMainFrame::GetMainFrame()->PostMessage(WM_COMMAND, ID_INTERNETUPDATE); } + +void CUpdateSetupDlg::OnResetURL() +//-------------------------------- +{ + SetDlgItemText(IDC_EDIT1, CUpdateCheck::defaultUpdateURL); +} Modified: trunk/OpenMPT/mptrack/UpdateCheck.h =================================================================== --- trunk/OpenMPT/mptrack/UpdateCheck.h 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/UpdateCheck.h 2011-04-13 17:44:31 UTC (rev 852) @@ -27,6 +27,8 @@ { public: + static const CString defaultUpdateURL; + // Force creation via "new" as we're using "delete this". static CUpdateCheck *Create(bool autoUpdate) { return new CUpdateCheck(autoUpdate); }; void DoUpdateCheck(); @@ -76,6 +78,7 @@ virtual BOOL OnSetActive(); afx_msg void OnSettingsChanged() { SetModified(TRUE); } afx_msg void OnCheckNow(); + afx_msg void OnResetURL(); DECLARE_MESSAGE_MAP() }; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-13 17:44:31 UTC (rev 852) @@ -534,7 +534,7 @@ if (!bNoMove) SetCurSel(m_dwStartSel, dwPos); if (!bScroll) return TRUE; // Scroll to row - row = dwPos >> 16; + row = GetRowFromCursor(dwPos); if (row < (int)pSndFile->Patterns[m_nPattern].GetNumRows()) { row += m_nMidRow; @@ -557,11 +557,11 @@ } } // Scroll to column - col = (dwPos & 0xFFFF) >> 3; + col = GetChanFromCursor(dwPos); if (col < (int)pSndFile->m_nChannels) { int maxcol = (rect.right - m_szHeader.cx) - 4; - maxcol -= GetColumnOffset(dwPos&7); + maxcol -= GetColumnOffset(GetColTypeFromCursor(dwPos)); maxcol /= GetColumnWidth(); if (col < xofs) { @@ -650,7 +650,7 @@ UINT nRepCnt = LOWORD(pMsg->lParam); UINT nFlags = HIWORD(pMsg->lParam); KeyEventType kT = ih->GetKeyEventType(nFlags); - InputTargetContext ctx = (InputTargetContext)(kCtxViewPatterns+1 + (m_dwCursor & 0x07)); + InputTargetContext ctx = (InputTargetContext)(kCtxViewPatterns + 1 + GetColTypeFromCursor(m_dwCursor)); if (ih->KeyEvent(ctx, nChar, nRepCnt, nFlags, kT) != kcNull) { return true; // Mapped to a command, no need to pass message on. @@ -771,20 +771,20 @@ DWORD endSel = ((m_dwBeginSel>>16)<(m_dwEndSel>>16)) ? m_dwEndSel : m_dwBeginSel; pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, 0, 0, pSndFile->m_nChannels, pSndFile->Patterns[m_nPattern].GetNumRows()); - int finalDest = (startSel>>16)+((endSel>>16)-(startSel>>16))*2; - for (int row=finalDest; row>(int)(startSel >> 16); row-=2) + int finalDest = GetRowFromCursor(startSel) + (GetRowFromCursor(endSel) - GetRowFromCursor(startSel))*2; + for (int row = finalDest; row > (int)GetRowFromCursor(startSel); row -= 2) { - int offset = row-(startSel>>16); - for (UINT i=(startSel & 0xFFFF); i<=(endSel & 0xFFFF); i++) if ((i & 7) <= LAST_COLUMN) + int offset = row - GetRowFromCursor(startSel); + for (UINT i=(startSel & 0xFFFF); i<=(endSel & 0xFFFF); i++) if (GetColTypeFromCursor(i) <= LAST_COLUMN) { - UINT chn = i >> 3; - if ((chn >= pSndFile->m_nChannels) || (row >= pSndFile->Patterns[m_nPattern].GetNumRows())) continue; - MODCOMMAND *dest = &p[row * pSndFile->m_nChannels + chn]; - MODCOMMAND *src = &p[(row-offset/2) * pSndFile->m_nChannels + chn]; - MODCOMMAND *blank= &p[(row-1) * pSndFile->m_nChannels + chn]; + UINT chn = GetChanFromCursor(i); + if ((chn >= pSndFile->GetNumChannels()) || (row >= pSndFile->Patterns[m_nPattern].GetNumRows())) continue; + MODCOMMAND *dest = &p[row * pSndFile->GetNumChannels() + chn]; + MODCOMMAND *src = &p[(row-offset/2) * pSndFile->GetNumChannels() + chn]; + MODCOMMAND *blank= &p[(row-1) * pSndFile->GetNumChannels() + chn]; //memcpy(dest/*+(i%5)*/, src/*+(i%5)*/, /*sizeof(MODCOMMAND) - (i-chn)*/ sizeof(BYTE)); //Log("dst: %d; src: %d; blk: %d\n", row, (row-offset/2), (row-1)); - switch(i & 7) + switch(GetColTypeFromCursor(i)) { case NOTE_COLUMN: dest->note = src->note; blank->note = NOTE_NONE; break; case INST_COLUMN: dest->instr = src->instr; blank->instr = 0; break; @@ -821,16 +821,16 @@ DWORD endSel = ((m_dwBeginSel>>16)<(m_dwEndSel>>16)) ? m_dwEndSel : m_dwBeginSel; pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, 0, 0, pSndFile->m_nChannels, pSndFile->Patterns[m_nPattern].GetNumRows()); - int finalDest = (startSel>>16)+((endSel>>16)-(startSel>>16))/2; + int finalDest = GetRowFromCursor(startSel) + (GetRowFromCursor(endSel) - GetRowFromCursor(startSel))/2; - for (int row=(startSel >> 16); row <= finalDest; row++) + for (int row = GetRowFromCursor(startSel); row <= finalDest; row++) { - int offset = row - (startSel >> 16); - int srcRow = (startSel >> 16) + (offset * 2); + int offset = row - GetRowFromCursor(startSel); + int srcRow = GetRowFromCursor(startSel) + (offset * 2); - for (UINT i = (startSel & 0xFFFF); i <= (endSel & 0xFFFF); i++) if ((i & 7) <= LAST_COLUMN) + for (UINT i = (startSel & 0xFFFF); i <= (endSel & 0xFFFF); i++) if (GetColTypeFromCursor(i) <= LAST_COLUMN) { - const CHANNELINDEX chn = i >> 3; + const CHANNELINDEX chn = GetChanFromCursor(i); if ((chn >= pSndFile->GetNumChannels()) || (srcRow >= pSndFile->Patterns[m_nPattern].GetNumRows()) || (row >= pSndFile->Patterns[m_nPattern].GetNumRows())) continue; MODCOMMAND *dest = pSndFile->Patterns[m_nPattern].GetpModCommand(row, chn); @@ -855,7 +855,7 @@ //memcpy(dest/*+(i%5)*/, src/*+(i%5)*/, /*sizeof(MODCOMMAND) - (i-chn)*/ sizeof(BYTE)); Log("dst: %d; src: %d\n", row, srcRow); - switch(i & 7) + switch(GetColTypeFromCursor(i)) { case NOTE_COLUMN: dest->note = src->note; break; case INST_COLUMN: dest->instr = src->instr; break; @@ -866,13 +866,13 @@ } } } - for (int row=finalDest+1; row<=(endSel>>16); row++) + for (int row = finalDest + 1; row <= GetRowFromCursor(endSel); row++) { - for (UINT i = (startSel & 0xFFFF); i <= (endSel & 0xFFFF); i++) if ((i & 7) <= LAST_COLUMN) + for (UINT i = (startSel & 0xFFFF); i <= (endSel & 0xFFFF); i++) if (GetColTypeFromCursor(i) <= LAST_COLUMN) { - UINT chn = i >> 3; + UINT chn = GetChanFromCursor(i); MODCOMMAND *dest = pSndFile->Patterns[m_nPattern].GetpModCommand(row, chn); - switch(i & 7) + switch(GetColTypeFromCursor(i)) { case NOTE_COLUMN: dest->note = NOTE_NONE; break; case INST_COLUMN: dest->instr = 0; break; @@ -919,13 +919,13 @@ DWORD tmp = m_dwEndSel; bool invalidateAllCols = false; - for (UINT row=(m_dwBeginSel >> 16); row<=(m_dwEndSel >> 16); row++) { // for all selected rows - for (UINT i=(m_dwBeginSel & 0xFFFF); i<=(m_dwEndSel & 0xFFFF); i++) if ((i & 7) < 5) { // for all selected cols + for (UINT row = GetRowFromCursor(m_dwBeginSel); row <= GetRowFromCursor(m_dwEndSel); row++) { // for all selected rows + for (UINT i=(m_dwBeginSel & 0xFFFF); i<=(m_dwEndSel & 0xFFFF); i++) if (GetColTypeFromCursor(i) <= LAST_COLUMN) { // for all selected cols - UINT chn = i >> 3; + UINT chn = GetChanFromCursor(i); if ((chn >= pSndFile->m_nChannels) || (row >= pSndFile->Patterns[m_nPattern].GetNumRows())) continue; MODCOMMAND *m = &p[row * pSndFile->m_nChannels + chn]; - switch(i & 7) + switch(GetColTypeFromCursor(i)) { case NOTE_COLUMN: // Clear note if (rm.note) @@ -982,7 +982,7 @@ // If selection ends on effect command column, extent invalidation area to // effect param column as well. - if ((tmp & 7) == EFFECT_COLUMN) + if (GetColTypeFromCursor(tmp) == EFFECT_COLUMN) tmp++; // If invalidation on all columns is wanted, extent invalidation area. @@ -1036,7 +1036,7 @@ { if (nFlags & MK_CONTROL) { - TogglePendingMute((GetPositionFromPoint(point)&0xFFFF)>>3); + TogglePendingMute(GetChanFromCursor(GetPositionFromPoint(point))); } } else if ((point.x >= m_szHeader.cx) && (point.y > m_szHeader.cy)) @@ -1057,7 +1057,7 @@ { // Set first selection point m_dwStartSel = GetPositionFromPoint(point); - if (((m_dwStartSel & 0xFFFF) >> 3) < pModDoc->GetNumChannels()) + if (GetChanFromCursor(m_dwStartSel) < pModDoc->GetNumChannels()) { m_dwStatus |= PATSTATUS_MOUSEDRAGSEL; @@ -1067,8 +1067,8 @@ } if ((CMainFrame::m_dwPatternSetup & PATTERN_DRAGNDROPEDIT) && ((m_dwBeginSel != m_dwEndSel) || (m_dwStatus & PATSTATUS_CTRLDRAGSEL)) - && ((m_dwStartSel >> 16) >= (m_dwBeginSel >> 16)) - && ((m_dwStartSel >> 16) <= (m_dwEndSel >> 16)) + && (GetRowFromCursor(m_dwStartSel) >= GetRowFromCursor(m_dwBeginSel)) + && (GetRowFromCursor(m_dwStartSel) <= GetRowFromCursor(m_dwEndSel)) && ((m_dwStartSel & 0xFFFF) >= (m_dwBeginSel & 0xFFFF)) && ((m_dwStartSel & 0xFFFF) <= (m_dwEndSel & 0xFFFF))) { @@ -1080,7 +1080,7 @@ } else { // Fix: Horizontal scrollbar pos screwed when selecting with mouse - SetCursorPosition( m_dwStartSel >> 16, m_dwStartSel & 0xFFFF ); + SetCursorPosition( GetRowFromCursor(m_dwStartSel), m_dwStartSel & 0xFFFF ); } } } @@ -1090,7 +1090,7 @@ // Mark row number => mark whole row (start) InvalidateSelection(); DWORD dwPoint = GetPositionFromPoint(point); - if((dwPoint >> 16) < pModDoc->GetSoundFile()->Patterns[m_nPattern].GetNumRows()) + if(GetRowFromCursor(dwPoint) < pModDoc->GetSoundFile()->Patterns[m_nPattern].GetNumRows()) { m_dwBeginSel = m_dwStartSel = dwPoint; m_dwEndSel = m_dwBeginSel | 0xFFFF; @@ -1156,7 +1156,7 @@ { DWORD dwPos = m_dwBeginSel; // Fix: Horizontal scrollbar pos screwed when selecting with mouse - SetCursorPosition( dwPos >> 16, dwPos & 0xFFFF ); + SetCursorPosition( GetRowFromCursor(dwPos), dwPos & 0xFFFF ); //UpdateIndicator(); } } @@ -1296,18 +1296,18 @@ m_nMenuParam = GetPositionFromPoint(pt); // Right-click outside selection? Reposition cursor to the new location - if (((m_nMenuParam >> 16) < (m_dwBeginSel >> 16)) - || ((m_nMenuParam >> 16) > (m_dwEndSel >> 16)) + if ((GetRowFromCursor(m_nMenuParam) < GetRowFromCursor(m_dwBeginSel)) + || (GetRowFromCursor(m_nMenuParam) > GetRowFromCursor(m_dwEndSel)) || ((m_nMenuParam & 0xFFFF) < (m_dwBeginSel & 0xFFFF)) || ((m_nMenuParam & 0xFFFF) > (m_dwEndSel & 0xFFFF))) { if (pt.y > m_szHeader.cy) { //ensure we're not clicking header // Fix: Horizontal scrollbar pos screwed when selecting with mouse - SetCursorPosition( m_nMenuParam >> 16, m_nMenuParam & 0xFFFF ); + SetCursorPosition( GetRowFromCursor(m_nMenuParam), m_nMenuParam & 0xFFFF ); } } - UINT nChn = (m_nMenuParam & 0xFFFF) >> 3; - if ((nChn < pSndFile->m_nChannels) && (pSndFile->Patterns[m_nPattern])) + const CHANNELINDEX nChn = GetChanFromCursor(m_nMenuParam); + if ((nChn < pSndFile->GetNumChannels()) && (pSndFile->Patterns[m_nPattern])) { CString MenuText; CInputHandler* ih = (CMainFrame::GetMainFrame())->GetInputHandler(); @@ -1434,7 +1434,7 @@ DWORD dwPos = GetPositionFromPoint(point); if ((pModDoc) && (m_nPattern < pModDoc->GetSoundFile()->Patterns.Size())) { - UINT row = dwPos >> 16; + UINT row = GetRowFromCursor(dwPos); UINT max = pModDoc->GetSoundFile()->Patterns[m_nPattern].GetNumRows(); if ((row) && (row >= max)) row = max-1; dwPos &= 0xFFFF; @@ -1462,7 +1462,7 @@ } else { // Fix: Horizontal scrollbar pos screwed when selecting with mouse - SetCursorPosition( dwPos >> 16, dwPos & 0xFFFF ); + SetCursorPosition( GetRowFromCursor(dwPos), dwPos & 0xFFFF ); } } } @@ -1537,21 +1537,20 @@ OnMuteChannel(false); } -void CViewPattern::OnMuteChannel(BOOL current) +void CViewPattern::OnMuteChannel(bool current) //-------------------------------------------- { CModDoc *pModDoc = GetDocument(); if (pModDoc) { - UINT nChn = current ? (m_dwCursor&0xFFFF)>>3 : (m_nMenuParam&0xFFFF)>>3; + const CHANNELINDEX nChn = GetChanFromCursor(current ? m_dwCursor : m_nMenuParam); pModDoc->SoloChannel(nChn, false); //rewbs.merge: recover old solo/mute behaviour pModDoc->MuteChannel(nChn, !pModDoc->IsChannelMuted(nChn)); //If we just unmuted a channel, make sure none are still considered "solo". if(!pModDoc->IsChannelMuted(nChn)) { - const CHANNELINDEX nNumChn = pModDoc->GetNumChannels(); - for(CHANNELINDEX i = 0; i < nNumChn; i++) + for(CHANNELINDEX i = 0; i < pModDoc->GetNumChannels(); i++) { pModDoc->SoloChannel(i, false); } @@ -1570,17 +1569,14 @@ // When trying to solo a channel that is already the only unmuted channel, // this will result in unmuting all channels, in order to satisfy user habits. // In all other cases, soloing a channel unsoloes all and mutes all except this channel -void CViewPattern::OnSoloChannel(BOOL current) +void CViewPattern::OnSoloChannel(bool current) //-------------------------------------------- { CModDoc *pModDoc = GetDocument(); - if (!pModDoc) { - return; - } + if (pModDoc == nullptr) return; - const CHANNELINDEX nNumChn = pModDoc->GetNumChannels(); - const CHANNELINDEX nChn = current ? (m_dwCursor&0xFFFF)>>3 : (m_nMenuParam&0xFFFF)>>3; - if (nChn >= nNumChn) + const CHANNELINDEX nChn = GetChanFromCursor(current ? m_dwCursor : m_nMenuParam); + if (nChn >= pModDoc->GetNumChannels()) { return; } @@ -1588,7 +1584,7 @@ if (pModDoc->IsChannelSolo(nChn)) { bool nChnIsOnlyUnMutedChan=true; - for (CHANNELINDEX i = 0; i < nNumChn; i++) //check status of all other chans + for (CHANNELINDEX i = 0; i < pModDoc->GetNumChannels(); i++) //check status of all other chans { if (i != nChn && !pModDoc->IsChannelMuted(i)) { @@ -1602,7 +1598,7 @@ return; } } - for(CHANNELINDEX i = 0; i < nNumChn; i++) + for(CHANNELINDEX i = 0; i < pModDoc->GetNumChannels(); i++) { pModDoc->MuteChannel(i, !(i == nChn)); //mute all chans except nChn, unmute nChn pModDoc->SoloChannel(i, (i == nChn)); //unsolo all chans except nChn, solo nChn @@ -1618,7 +1614,7 @@ if (pModDoc) { UINT nNumChn = pModDoc->GetNumChannels(); - UINT nChn = (m_nMenuParam & 0xFFFF) >> 3; + UINT nChn = GetChanFromCursor(m_nMenuParam); if (nChn < nNumChn) { // MultiRecordMask[nChn>>3] ^= (1 << (nChn & 7)); @@ -1638,7 +1634,7 @@ CModDoc *pModDoc = GetDocument(); if (pModDoc){ UINT nNumChn = pModDoc->GetNumChannels(); - UINT nChn = (m_nMenuParam & 0xFFFF) >> 3; + UINT nChn = GetChanFromCursor(m_nMenuParam); if (nChn < nNumChn){ pModDoc->Record2Channel(nChn); InvalidateChannelsHeaders(); @@ -1675,7 +1671,7 @@ if (!pModDoc || !( IsEditingEnabled_bmsg() )) return; pSndFile = pModDoc->GetSoundFile(); if (!pSndFile->Patterns[m_nPattern]) return; - row = m_dwBeginSel >> 16; + row = GetRowFromCursor(m_dwBeginSel); maxrow = pSndFile->Patterns[m_nPattern].GetNumRows(); if (colmax >= pSndFile->m_nChannels) colmax = pSndFile->m_nChannels-1; if (colmin > colmax) return; @@ -1695,10 +1691,10 @@ } } //rewbs.customKeys - DWORD finalPos = (min(m_dwEndSel >> 16, m_dwBeginSel >> 16) << 16 | (m_dwEndSel & 0xFFFF)); + DWORD finalPos = (GetSelectionStartRow() << 16) | (m_dwEndSel & 0xFFFF); SetCurSel(finalPos, finalPos); // Fix: Horizontal scrollbar pos screwed when selecting with mouse - SetCursorPosition( finalPos >> 16, finalPos & 0xFFFF ); + SetCursorPosition( GetRowFromCursor(finalPos), finalPos & 0xFFFF ); //end rewbs.customKeys pModDoc->SetModified(); @@ -1710,9 +1706,9 @@ void CViewPattern::OnDeleteRows() //------------------------------- { - UINT colmin = (m_dwBeginSel & 0xFFFF) >> 3; - UINT colmax = (m_dwEndSel & 0xFFFF) >> 3; - UINT nrows = (m_dwEndSel >> 16) - (m_dwBeginSel >> 16) + 1; + UINT colmin = GetChanFromCursor(m_dwBeginSel); + UINT colmax = GetChanFromCursor(m_dwEndSel); + UINT nrows = GetRowFromCursor(m_dwEndSel) - GetRowFromCursor(m_dwBeginSel) + 1; DeleteRows(colmin, colmax, nrows); //m_dwEndSel = (m_dwEndSel & 0x0000FFFF) | (m_dwBeginSel & 0xFFFF0000); } @@ -1724,8 +1720,8 @@ CModDoc *pModDoc = GetDocument(); if (!pModDoc) return; CSoundFile *pSndFile = pModDoc->GetSoundFile(); - UINT nrows = (m_dwEndSel >> 16) - (m_dwBeginSel >> 16) + 1; - DeleteRows(0, pSndFile->m_nChannels-1, nrows); + UINT nrows = GetRowFromCursor(m_dwEndSel) - GetRowFromCursor(m_dwBeginSel) + 1; + DeleteRows(0, pSndFile->GetNumChannels() - 1, nrows); m_dwEndSel = (m_dwEndSel & 0x0000FFFF) | (m_dwBeginSel & 0xFFFF0000); } @@ -1739,16 +1735,16 @@ if (!pModDoc || !(IsEditingEnabled_bmsg())) return; pSndFile = pModDoc->GetSoundFile(); if (!pSndFile->Patterns[m_nPattern]) return; - row = m_dwBeginSel >> 16; + row = GetRowFromCursor(m_dwBeginSel); maxrow = pSndFile->Patterns[m_nPattern].GetNumRows(); - if (colmax >= pSndFile->m_nChannels) colmax = pSndFile->m_nChannels-1; + if (colmax >= pSndFile->GetNumChannels()) colmax = pSndFile->GetNumChannels() - 1; if (colmin > colmax) return; - pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, 0,0, pSndFile->m_nChannels, maxrow); + pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, 0,0, pSndFile->GetNumChannels(), maxrow); for (UINT r=maxrow; r>row; ) { r--; - MODCOMMAND *m = pSndFile->Patterns[m_nPattern] + r * pSndFile->m_nChannels + colmin; + MODCOMMAND *m = pSndFile->Patterns[m_nPattern] + r * pSndFile->GetNumChannels() + colmin; for (UINT c=colmin; c<=colmax; c++, m++) { if (r <= row) @@ -1756,7 +1752,7 @@ m->Clear(); } else { - *m = *(m - pSndFile->m_nChannels); + *m = *(m - pSndFile->GetNumChannels()); } } } @@ -1779,8 +1775,8 @@ if (!pSndFile->Patterns[m_nPattern]) return; row = m_nRow; maxrow = pSndFile->Patterns[m_nPattern].GetNumRows(); - colmin = (m_dwBeginSel & 0xFFFF) >> 3; - colmax = (m_dwEndSel & 0xFFFF) >> 3; + colmin = GetChanFromCursor(m_dwBeginSel); + colmax = GetChanFromCursor(m_dwEndSel); InsertRows(colmin, colmax); } @@ -1865,7 +1861,7 @@ { CSoundFile* pSndFile = pModDoc->GetSoundFile(); UINT nCurrentOrder = SendCtrlMessage(CTRLMSG_GETCURRENTORDER); - UINT nCurrentChannel = ((m_dwCursor & 0xFFFF) >> 3) + 1; + UINT nCurrentChannel = GetChanFromCursor(m_dwCursor) + 1; m_pGotoWnd->UpdatePos(m_nRow, nCurrentChannel, m_nPattern, nCurrentOrder, pSndFile); @@ -2179,8 +2175,8 @@ CSoundFile *pSndFile = pModDoc->GetSoundFile(); if ((!pSndFile->Patterns.IsValidPat(m_nPattern)) || (!pSndFile->Patterns[m_nPattern].GetNumRows())) return; BEGIN_CRITICAL(); - // Cut instrument\xB4s/samples in virtual channels - for (CHANNELINDEX i = pSndFile->m_nChannels; i < MAX_CHANNELS; i++) + // Cut instruments/samples in virtual channels + for (CHANNELINDEX i = pSndFile->GetNumChannels(); i < MAX_CHANNELS; i++) { pSndFile->Chn[i].dwFlags |= CHN_NOTEFADE | CHN_KEYOFF; } @@ -2215,8 +2211,8 @@ { CSoundFile *pSndFile = pModDoc->GetSoundFile(); if ((!pSndFile->Patterns[m_nPattern].GetNumRows()) || (!pSndFile->Patterns[m_nPattern])) return; - MODCOMMAND *m = pSndFile->Patterns[m_nPattern] + m_nRow * pSndFile->m_nChannels + ((m_dwCursor & 0xFFFF) >> 3); - switch(m_dwCursor & 7) + MODCOMMAND *m = pSndFile->Patterns[m_nPattern] + m_nRow * pSndFile->GetNumChannels() + GetChanFromCursor(m_dwCursor); + switch(GetColTypeFromCursor(m_dwCursor)) { case NOTE_COLUMN: case INST_COLUMN: @@ -2247,8 +2243,8 @@ if ((pModDoc) && (pMainFrm) && (IsEditingEnabled_bmsg())) { PrepareUndo(m_dwBeginSel, m_dwEndSel); - UINT nChn = (m_dwCursor & 0xFFFF) >> 3; - UINT nCursor = m_dwCursor & 0x07; + UINT nChn = GetChanFromCursor(m_dwCursor); + UINT nCursor = GetColTypeFromCursor(m_dwCursor); CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *p = pSndFile->Patterns[m_nPattern] + m_nRow*pSndFile->m_nChannels + nChn; @@ -2311,7 +2307,7 @@ if (pModDoc) { //CSoundFile *pSndFile = pModDoc->GetSoundFile(); - UINT row0 = m_dwBeginSel >> 16, row1 = m_dwEndSel >> 16, nchn = (m_dwBeginSel & 0xFFFF) >> 3; + UINT row0 = GetRowFromCursor(m_dwBeginSel), row1 = GetRowFromCursor(m_dwEndSel), nchn = GetChanFromCursor(m_dwBeginSel); if (m_pEffectVis) { //window already there, update data @@ -2529,8 +2525,8 @@ CModDoc *pModDoc = GetDocument(); if (pModDoc) { - const UINT row0 = m_dwBeginSel >> 16, row1 = m_dwEndSel >> 16; - const UINT col0 = ((m_dwBeginSel & 0xFFFF)+7) >> 3, col1 = (m_dwEndSel & 0xFFFF) >> 3; + const UINT row0 = GetRowFromCursor(m_dwBeginSel), row1 = GetRowFromCursor(m_dwEndSel); + const UINT col0 = ((m_dwBeginSel & 0xFFFF)+7) >> 3, col1 = GetChanFromCursor(m_dwEndSel); CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *pcmd = pSndFile->Patterns[m_nPattern]; const MODCOMMAND::NOTE noteMin = pSndFile->GetModSpecifications().noteMin; @@ -2578,7 +2574,7 @@ pOldPattern = pSndFile->Patterns[m_nPattern]; if ((nChannels < 1) || (nRows < 1) || (!pOldPattern)) return; dx = (int)((m_dwDragPos & 0xFFF8) >> 3) - (int)((m_dwStartSel & 0xFFF8) >> 3); - dy = (int)(m_dwDragPos >> 16) - (int)(m_dwStartSel >> 16); + dy = (int)GetRowFromCursor(m_dwDragPos) - (int)GetRowFromCursor(m_dwStartSel); if ((!dx) && (!dy)) return; pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, 0,0, nChannels, nRows); pNewPattern = CPattern::AllocatePattern(nRows, nChannels); @@ -3711,12 +3707,12 @@ SetCurrentColumn(m_dwCursor + 1); return wParam; case kcNavigateNextChanSelect: - case kcNavigateNextChan:SetCurrentColumn(((((m_dwCursor >> 3) + 1) % pSndFile->m_nChannels) << 3) | (m_dwCursor & 0x07)); return wParam; + case kcNavigateNextChan: SetCurrentColumn((((GetChanFromCursor(m_dwCursor) + 1) % pSndFile->m_nChannels) << 3) | GetColTypeFromCursor(m_dwCursor)); return wParam; case kcNavigatePrevChanSelect: - case kcNavigatePrevChan:{if (m_dwCursor >> 3) - SetCurrentColumn(((((m_dwCursor >> 3) - 1) % pSndFile->m_nChannels) << 3) | (m_dwCursor & 0x07)); + case kcNavigatePrevChan:{if(GetChanFromCursor(m_dwCursor) > 0) + SetCurrentColumn((((GetChanFromCursor(m_dwCursor) - 1) % pSndFile->m_nChannels) << 3) | GetColTypeFromCursor(m_dwCursor)); else - SetCurrentColumn((m_dwCursor & 0x07) | ((pSndFile->m_nChannels-1) << 3)); + SetCurrentColumn(GetColTypeFromCursor(m_dwCursor) | ((pSndFile->m_nChannels-1) << 3)); UINT n = (m_nRow << 16) | (m_dwCursor); SetCurSel(n, n); return wParam;} @@ -3776,11 +3772,11 @@ SelectBeatOrMeasure(wParam == kcSelectBeat); return wParam; case kcClearRow: OnClearField(-1, false); return wParam; - case kcClearField: OnClearField(m_dwCursor & 0x07, false); return wParam; - case kcClearFieldITStyle: OnClearField(m_dwCursor & 0x07, false, true); return wParam; + case kcClearField: OnClearField(GetColTypeFromCursor(m_dwCursor), false); return wParam; + case kcClearFieldITStyle: OnClearField(GetColTypeFromCursor(m_dwCursor), false, true); return wParam; case kcClearRowStep: OnClearField(-1, true); return wParam; - case kcClearFieldStep: OnClearField(m_dwCursor & 0x07, true); return wParam; - case kcClearFieldStepITStyle: OnClearField(m_dwCursor & 0x07, true, true); return wParam; + case kcClearFieldStep: OnClearField(GetColTypeFromCursor(m_dwCursor), true); return wParam; + case kcClearFieldStepITStyle: OnClearField(GetColTypeFromCursor(m_dwCursor), true, true); return wParam; case kcDeleteRows: OnDeleteRows(); return wParam; case kcDeleteAllRows: DeleteRows(0, pSndFile->m_nChannels-1,1); return wParam; case kcInsertRow: OnInsertRows(); return wParam; @@ -3822,7 +3818,7 @@ case kcEditPasteFlood: OnEditPasteFlood(); return wParam; case kcEditPushForwardPaste: OnEditPushForwardPaste(); return wParam; case kcEditSelectAll: OnEditSelectAll(); return wParam; - case kcTogglePluginEditor: TogglePluginEditor((m_dwCursor & 0xFFFF) >> 3); return wParam; + case kcTogglePluginEditor: TogglePluginEditor(GetChanFromCursor(m_dwCursor)); return wParam; case kcToggleFollowSong: SendCtrlMessage(CTRLMSG_PAT_FOLLOWSONG, 1); return wParam; case kcChangeLoopStatus: SendCtrlMessage(CTRLMSG_PAT_LOOP, -1); return wParam; case kcNewPattern: SendCtrlMessage(CTRLMSG_PAT_NEWPATTERN); return wParam; @@ -4151,7 +4147,7 @@ //Enter note off in pattern? if ((note < NOTE_MIN) || (note > NOTE_MAX)) return; - if ((m_dwCursor & 7) > 1 && (bChordMode || !fromMidi)) + if (GetColTypeFromCursor(m_dwCursor) > INST_COLUMN && (bChordMode || !fromMidi)) return; if (!pModDoc || !pMainFrm || !(IsEditingEnabled())) return; @@ -4779,7 +4775,7 @@ } PrepareUndo(m_dwBeginSel, m_dwEndSel); - UINT nChn = (m_dwCursor & 0xFFFF) >> 3; + UINT nChn = GetChanFromCursor(m_dwCursor); CSoundFile *pSndFile = pModDoc->GetSoundFile(); MODCOMMAND *p = pSndFile->Patterns[m_nPattern] + m_nRow*pSndFile->m_nChannels + nChn; MODCOMMAND oldcmd = *p; @@ -5389,23 +5385,27 @@ } -UINT CViewPattern::GetSelectionStartRow() { -//----------------------------------------- +ROWINDEX CViewPattern::GetSelectionStartRow() +//------------------------------------------- +{ return min(GetRowFromCursor(m_dwBeginSel), GetRowFromCursor(m_dwEndSel)); } -UINT CViewPattern::GetSelectionEndRow() { -//--------------------------------------- +ROWINDEX CViewPattern::GetSelectionEndRow() +//----------------------------------------- +{ return max(GetRowFromCursor(m_dwBeginSel), GetRowFromCursor(m_dwEndSel)); } -UINT CViewPattern::GetSelectionStartChan() { -//------------------------------------------ +CHANNELINDEX CViewPattern::GetSelectionStartChan() +//------------------------------------------------ +{ return min(GetChanFromCursor(m_dwBeginSel), GetChanFromCursor(m_dwEndSel)); } -UINT CViewPattern::GetSelectionEndChan() { -//---------------------------------------- +CHANNELINDEX CViewPattern::GetSelectionEndChan() +//---------------------------------------------- +{ return max(GetChanFromCursor(m_dwBeginSel), GetChanFromCursor(m_dwEndSel)); } @@ -5428,16 +5428,7 @@ return chans.GetCount(); } -ROWINDEX CViewPattern::GetRowFromCursor(DWORD cursor) {return cursor >> 16;} -//--------------------------------------------------- - -CHANNELINDEX CViewPattern::GetChanFromCursor(DWORD cursor) {return static_cast<CHANNELINDEX>((cursor & 0xFFFF) >> 3);} -//------------------------------------------------------- -UINT CViewPattern::GetColTypeFromCursor(DWORD cursor) {return cursor & 0x07;} -//--------------------------------------------------- - - bool CViewPattern::IsInterpolationPossible(ROWINDEX startRow, ROWINDEX endRow, CHANNELINDEX chan, PatternColumns colType, CSoundFile* pSndFile) //-------------------------------------------------------------------------------------- @@ -5486,7 +5477,7 @@ void CViewPattern::OnTogglePendingMuteFromClick() //----------------------------------------------- { - TogglePendingMute((m_nMenuParam&0xFFFF)>>3); + TogglePendingMute(GetChanFromCursor(m_nMenuParam)); } void CViewPattern::OnPendingSoloChnFromClick() @@ -5752,7 +5743,7 @@ } else if(startRow == GetSelectionStartRow() && endRow == GetSelectionEndRow()) { // Whole beat or measure is already selected - if((m_dwBeginSel & 0x07) == 0 && (m_dwEndSel & 0x07) == LAST_COLUMN) + if(GetColTypeFromCursor(m_dwBeginSel) == NOTE_COLUMN && GetColTypeFromCursor(m_dwEndSel) == LAST_COLUMN) { // Whole channel is already selected => expand selection to whole row. startMask = 0; @@ -5766,8 +5757,8 @@ else { // Some arbitrary selection: Remember start / end column - startMask |= (m_dwBeginSel & 0x07); - endMask |= (m_dwEndSel & 0x07); + startMask |= GetColTypeFromCursor(m_dwBeginSel); + endMask |= GetColTypeFromCursor(m_dwEndSel); } SetCurSel((startRow << 16) | startMask, (endRow << 16) | endMask); } Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/View_pat.h 2011-04-13 17:44:31 UTC (rev 852) @@ -282,8 +282,8 @@ afx_msg void OnTogglePendingMuteFromClick(); //rewbs.customKeys afx_msg void OnPendingSoloChnFromClick(); afx_msg void OnPendingUnmuteAllChnFromClick(); - afx_msg void OnSoloChannel(BOOL current); //rewbs.customKeys - afx_msg void OnMuteChannel(BOOL current); //rewbs.customKeys + afx_msg void OnSoloChannel(bool current); //rewbs.customKeys + afx_msg void OnMuteChannel(bool current); //rewbs.customKeys afx_msg void OnUnmuteAll(); afx_msg void OnRecordSelect(); // -> CODE#0012 @@ -367,15 +367,15 @@ bool BuildChannelMiscCtxMenu(HMENU hMenu, CSoundFile* pSndFile); bool BuildPCNoteCtxMenu(HMENU hMenu, CInputHandler* ih, CSoundFile* pSndFile); - UINT GetSelectionStartRow(); - UINT GetSelectionEndRow(); - UINT GetSelectionStartChan(); - UINT GetSelectionEndChan(); + ROWINDEX GetSelectionStartRow(); + ROWINDEX GetSelectionEndRow(); + CHANNELINDEX GetSelectionStartChan(); + CHANNELINDEX GetSelectionEndChan(); UINT ListChansWhereColSelected(PatternColumns colType, CArray<UINT,UINT> &chans); - static ROWINDEX GetRowFromCursor(DWORD cursor); - static CHANNELINDEX GetChanFromCursor(DWORD cursor); - static UINT GetColTypeFromCursor(DWORD cursor); + static ROWINDEX GetRowFromCursor(DWORD cursor) { return (cursor >> 16); }; + static CHANNELINDEX GetChanFromCursor(DWORD cursor) { return static_cast<CHANNELINDEX>((cursor & 0xFFFF) >> 3); }; + static UINT GetColTypeFromCursor(DWORD cursor) { return (cursor & 0x07); }; bool IsInterpolationPossible(ROWINDEX startRow, ROWINDEX endRow, CHANNELINDEX chan, PatternColumns colType, CSoundFile* pSndFile); void Interpolate(PatternColumns type); Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2011-04-13 13:44:49 UTC (rev 851) +++ trunk/OpenMPT/mptrack/mptrack.rc 2011-04-13 17:44:31 UTC (rev 852) @@ -197,11 +197,12 @@ CONTROL "Weekly (recommended)",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,12,42,240,8 CONTROL "Monthly",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,12,54,240,8 GROUPBOX "Advanced Settings",IDC_STATIC,6,78,258,60 - LTEXT "Update server URL:",IDC_STATIC,12,90,246,8 + LTEXT "Update server URL:",IDC_STATIC,12,90,186,8 EDITTEXT IDC_EDIT1,12,102,246,12,ES_AUTOHSCROLL LTEXT "",IDC_LASTUPDATE,6,168,258,24 LTEXT "Do not change this unless you are absolutely sure of what you are doing.",IDC_STATIC,12,120,246,12 PUSHBUTTON "Check for Updates",IDC_BUTTON1,6,144,84,18 + PUSHBUTTON "Reset",IDC_BUTTON2,204,87,54,12 END This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-13 20:38:35
|
Revision: 854 http://modplug.svn.sourceforge.net/modplug/?rev=854&view=rev Author: saga-games Date: 2011-04-13 20:38:28 +0000 (Wed, 13 Apr 2011) Log Message: ----------- [Fix] XM Saving: In compatible mode, the number of samples per instrument is now limited to 16. [Ref] Eliminating more duplicate code... Modified Paths: -------------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp 2011-04-13 20:00:31 UTC (rev 853) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2011-04-13 20:38:28 UTC (rev 854) @@ -528,10 +528,9 @@ if(pSndFile == nullptr) return false; CHAR s[512]; - vector<bool> bIns; - int nExt = 0; + vector<bool> samplesUsed; int nRemoved = 0; - bIns.resize(pSndFile->GetNumSamples() + 1, false); + samplesUsed.resize(pSndFile->GetNumSamples() + 1, false); BeginWaitCursor(); for (SAMPLEINDEX nSmp = pSndFile->m_nSamples; nSmp >= 1; nSmp--) if (pSndFile->Samples[nSmp].pSample) @@ -546,49 +545,12 @@ nRemoved++; } } - if (pSndFile->m_nInstruments) - { - for (PATTERNINDEX nPat = 0; nPat < pSndFile->GetNumPatterns(); nPat++) - { - MODCOMMAND *p = pSndFile->Patterns[nPat]; - if (p) - { - UINT jmax = pSndFile->Patterns[nPat].GetNumRows() * pSndFile->GetNumChannels(); - for (UINT j=0; j<jmax; j++, p++) - { - if ((p->note) && (p->note <= NOTE_MAX) && (!p->IsPcNote())) - { - if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) - { - MODINSTRUMENT *pIns = pSndFile->Instruments[p->instr]; - if (pIns) - { - UINT n = pIns->Keyboard[p->note-1]; - if (n <= pSndFile->GetNumSamples()) bIns[n] = true; - } - } else - { - for (UINT k=1; k<=pSndFile->m_nInstruments; k++) - { - MODINSTRUMENT *pIns = pSndFile->Instruments[k]; - if (pIns) - { - UINT n = pIns->Keyboard[p->note-1]; - if (n <= pSndFile->GetNumSamples()) bIns[n] = true; - } - } - } - } - } - } - } - for (SAMPLEINDEX ichk = 1; ichk <= pSndFile->GetNumSamples(); ichk++) - { - if ((!bIns[ichk]) && (pSndFile->Samples[ichk].pSample)) nExt++; - } - } + + SAMPLEINDEX nExt = pSndFile->DetectUnusedSamples(samplesUsed); + EndWaitCursor(); - if (nExt && !((pSndFile->GetType() == MOD_TYPE_IT) && (pSndFile->m_dwSongFlags & SONG_ITPROJECT))) + + if (nExt && !((pSndFile->GetType() == MOD_TYPE_IT) && (pSndFile->m_dwSongFlags & SONG_ITPROJECT))) { //We don't remove an instrument's unused samples in an ITP. wsprintf(s, "OpenMPT detected %d sample%s referenced by an instrument,\n" "but not used in the song. Do you want to remove them?", nExt, (nExt == 1) ? "" : "s"); @@ -596,7 +558,7 @@ { for (SAMPLEINDEX nSmp = 1; nSmp <= pSndFile->GetNumSamples(); nSmp++) { - if ((!bIns[nSmp]) && (pSndFile->Samples[nSmp].pSample)) + if ((!samplesUsed[nSmp]) && (pSndFile->Samples[nSmp].pSample)) { m_pModDoc->GetSampleUndo()->PrepareUndo(nSmp, sundo_delete); BEGIN_CRITICAL(); Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2011-04-13 20:00:31 UTC (rev 853) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2011-04-13 20:38:28 UTC (rev 854) @@ -175,7 +175,7 @@ p->command = src[j++]; p->param = src[j++]; } - if (p->note == 97) p->note = 0xFF; else + if (p->note == 97) p->note = NOTE_KEYOFF; else if ((p->note) && (p->note < 97)) p->note += 12; if (p->command | p->param) pSndFile->ConvertModCommand(p); if (p->instr == 0xff) p->instr = 0; @@ -241,8 +241,6 @@ XMSAMPLEHEADER xmsh; XMSAMPLESTRUCT xmss; DWORD dwMemPos; - BYTE samples_used[(MAX_SAMPLES + 7) / 8]; // for removing unused samples - UINT unused_samples; // dito bool bMadeWithModPlug = false, bProbablyMadeWithModPlug = false, bProbablyMPT109 = false, bIsFT2 = false; @@ -300,8 +298,8 @@ if(dwMemPos == 0) return true; } - memset(samples_used, 0, sizeof(samples_used)); - unused_samples = 0; + vector<bool> samples_used; // for removing unused samples + SAMPLEINDEX unused_samples = 0; // dito // Reading instruments for (INSTRUMENTINDEX iIns = 1; iIns <= m_nInstruments; iIns++) @@ -316,7 +314,7 @@ DWORD ihsize = LittleEndian(*((DWORD *)(lpStream + dwMemPos))); if (dwMemPos + ihsize > dwMemLength) return true; - memset(&pih, 0, sizeof(pih)); + MemsetZero(pih); memcpy(&pih, lpStream + dwMemPos, min(sizeof(pih), ihsize)); if ((Instruments[iIns] = new MODINSTRUMENT) == nullptr) continue; @@ -357,6 +355,7 @@ bIsFT2 = true; // definitely not MPT. (or any other tracker) } + if (LittleEndian(pih.size)) dwMemPos += LittleEndian(pih.size); else @@ -400,14 +399,14 @@ if (!unused_samples) { unused_samples = DetectUnusedSamples(samples_used); - if (!unused_samples) unused_samples = 0xFFFF; + if (!unused_samples) unused_samples = SAMPLEINDEX_INVALID; } - if ((unused_samples) && (unused_samples != 0xFFFF)) + if ((unused_samples) && (unused_samples != SAMPLEINDEX_INVALID)) { - for (UINT iext=m_nSamples; iext>=1; iext--) if (0 == (samples_used[iext>>3] & (1<<(iext&7)))) + for (UINT iext=m_nSamples; iext>=1; iext--) if (!samples_used[iext]) { unused_samples--; - samples_used[iext>>3] |= (1<<(iext&7)); + samples_used[iext] = true; DestroySample(iext); n = iext; for (UINT mapchk=0; mapchk<nmap; mapchk++) @@ -422,7 +421,7 @@ if (pks->Keyboard[ks] == n) pks->Keyboard[ks] = 0; } } - memset(&Samples[n], 0, sizeof(Samples[0])); + MemsetZero(Samples[n]); break; } } @@ -836,7 +835,7 @@ UINT param = ModSaveCommand(p, true, bCompatibilityExport); UINT command = param >> 8; param &= 0xFF; - if (note >= 0xFE) note = 97; else + if (note >= NOTE_MIN_SPECIAL) note = 97; else if ((note <= 12) || (note > 96+12)) note = 0; else note -= 12; UINT vol = 0; @@ -993,7 +992,7 @@ smptable[xmih.samples++] = sample; //record in instrument's sample table } - if (xmih.samples >= 32) break; + if ((xmih.samples >= 32) || (xmih.samples >= 16 && bCompatibilityExport)) break; xmsh.snum[j] = k; //record sample table offset in instrument's note map } } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 20:00:31 UTC (rev 853) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 20:38:28 UTC (rev 854) @@ -2550,54 +2550,58 @@ } -UINT CSoundFile::DetectUnusedSamples(BYTE *pbIns) -//----------------------------------------------- +SAMPLEINDEX CSoundFile::DetectUnusedSamples(vector<bool> &sampleUsed) +//------------------------------------------------------------------- { - UINT nExt = 0; + sampleUsed.assign(GetNumSamples() + 1, false); - if (!pbIns) return 0; - if (m_nInstruments) + if(GetNumInstruments() == 0) { - memset(pbIns, 0, (MAX_SAMPLES+7)/8); - for (UINT ipat=0; ipat<Patterns.Size(); ipat++) + return 0; + } + SAMPLEINDEX nExt = 0; + + for (PATTERNINDEX nPat = 0; nPat < GetNumPatterns(); nPat++) + { + const MODCOMMAND *p = Patterns[nPat]; + if(p == nullptr) { - MODCOMMAND *p = Patterns[ipat]; - if (p) + continue; + } + + UINT jmax = Patterns[nPat].GetNumRows() * GetNumChannels(); + for (UINT j=0; j<jmax; j++, p++) + { + if ((p->note) && (p->note <= NOTE_MAX) && (!p->IsPcNote())) { - UINT jmax = Patterns[ipat].GetNumRows() * m_nChannels; - for (UINT j=0; j<jmax; j++, p++) + if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) { - if ((p->note) && (p->note <= NOTE_MAX)) + MODINSTRUMENT *pIns = Instruments[p->instr]; + if (pIns) { - if ((p->instr) && (p->instr < MAX_INSTRUMENTS)) + SAMPLEINDEX n = pIns->Keyboard[p->note-1]; + if (n <= GetNumSamples()) sampleUsed[n] = true; + } + } else + { + for (INSTRUMENTINDEX k = GetNumInstruments(); k >= 1; k--) + { + MODINSTRUMENT *pIns = Instruments[k]; + if (pIns) { - MODINSTRUMENT *pIns = Instruments[p->instr]; - if (pIns) - { - UINT n = pIns->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) pbIns[n>>3] |= 1<<(n&7); - } - } else - { - for (UINT k=1; k<=m_nInstruments; k++) - { - MODINSTRUMENT *pIns = Instruments[k]; - if (pIns) - { - UINT n = pIns->Keyboard[p->note-1]; - if (n < MAX_SAMPLES) pbIns[n>>3] |= 1<<(n&7); - } - } + SAMPLEINDEX n = pIns->Keyboard[p->note-1]; + if (n <= GetNumSamples()) sampleUsed[n] = true; } } } } } - for (UINT ichk=1; ichk<=m_nSamples; ichk++) - { - if ((0 == (pbIns[ichk>>3]&(1<<(ichk&7)))) && (Samples[ichk].pSample)) nExt++; - } } + for (SAMPLEINDEX ichk = GetNumSamples(); ichk >= 1; ichk--) + { + if ((!sampleUsed[ichk]) && (Samples[ichk].pSample)) nExt++; + } + return nExt; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 20:00:31 UTC (rev 853) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 20:38:28 UTC (rev 854) @@ -951,7 +951,7 @@ bool IsSampleUsed(SAMPLEINDEX nSample); bool IsInstrumentUsed(INSTRUMENTINDEX nInstr); bool RemoveInstrumentSamples(INSTRUMENTINDEX nInstr); - UINT DetectUnusedSamples(BYTE *); // bitmask + SAMPLEINDEX DetectUnusedSamples(vector<bool> &sampleUsed); bool RemoveSelectedSamples(bool *pbIns); void AdjustSampleLoop(MODSAMPLE *pSmp); // Samples file I/O This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-14 14:23:46
|
Revision: 855 http://modplug.svn.sourceforge.net/modplug/?rev=855&view=rev Author: saga-games Date: 2011-04-14 14:23:39 +0000 (Thu, 14 Apr 2011) Log Message: ----------- [Fix] Song Cleanup: When converting instruments to samples, "Remove samples associated with an instrument" actually destroyed all samples. Removed this checkbox as the sample cleanup options can be used to do the same. [Ref] More code cleanup... Modified Paths: -------------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/soundlib/Sampleio.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/modsmp_ctrl.cpp Modified: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp 2011-04-13 20:38:28 UTC (rev 854) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2011-04-14 14:23:39 UTC (rev 855) @@ -528,23 +528,20 @@ if(pSndFile == nullptr) return false; CHAR s[512]; - vector<bool> samplesUsed; - int nRemoved = 0; - samplesUsed.resize(pSndFile->GetNumSamples() + 1, false); + vector<bool> samplesUsed(pSndFile->GetNumSamples() + 1, true); BeginWaitCursor(); - for (SAMPLEINDEX nSmp = pSndFile->m_nSamples; nSmp >= 1; nSmp--) if (pSndFile->Samples[nSmp].pSample) + for (SAMPLEINDEX nSmp = pSndFile->GetNumSamples(); nSmp >= 1; nSmp--) if (pSndFile->Samples[nSmp].pSample) { if (!pSndFile->IsSampleUsed(nSmp)) { + samplesUsed[nSmp] = false; m_pModDoc->GetSampleUndo()->PrepareUndo(nSmp, sundo_delete); - BEGIN_CRITICAL(); - pSndFile->DestroySample(nSmp); - if ((nSmp == pSndFile->m_nSamples) && (nSmp > 1)) pSndFile->m_nSamples--; - END_CRITICAL(); - nRemoved++; } } + BEGIN_CRITICAL(); + SAMPLEINDEX nRemoved = pSndFile->RemoveSelectedSamples(samplesUsed); + END_CRITICAL(); SAMPLEINDEX nExt = pSndFile->DetectUnusedSamples(samplesUsed); @@ -569,7 +566,7 @@ m_pModDoc->GetSampleUndo()->ClearUndo(nSmp); } } - wsprintf(s, "%d unused sample%s removed\n" ,nRemoved, (nRemoved == 1) ? "" : "s"); + wsprintf(s, "%d unused sample%s removed\n" , nRemoved, (nRemoved == 1) ? "" : "s"); m_pModDoc->AddToLog(s); return true; } @@ -971,19 +968,17 @@ CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); if(pSndFile == nullptr) return false; - if (pSndFile->m_nSamples == 0) return false; - for (SAMPLEINDEX nSmp = 1; nSmp <= pSndFile->m_nSamples; nSmp++) + if (pSndFile->GetNumSamples() == 0) return false; + vector<bool> keepSamples(pSndFile->GetNumSamples() + 1, false); + + for (SAMPLEINDEX nSmp = 1; nSmp <= pSndFile->GetNumSamples(); nSmp++) { m_pModDoc->GetSampleUndo()->PrepareUndo(nSmp, sundo_delete, 0, pSndFile->Samples[nSmp].nLength); - if(pSndFile->Samples[nSmp].pSample) - { - BEGIN_CRITICAL(); - pSndFile->DestroySample(nSmp); - END_CRITICAL(); - } } ctrlSmp::ResetSamples(*pSndFile, ctrlSmp::SmpResetInit); - pSndFile->m_nSamples = 1; + BEGIN_CRITICAL(); + pSndFile->RemoveSelectedSamples(keepSamples); + END_CRITICAL(); return true; } @@ -994,27 +989,20 @@ CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); if(pSndFile == nullptr) return false; - if (pSndFile->m_nInstruments == 0) return false; + if (pSndFile->GetNumInstruments() == 0) return false; - char removeSamples = -1; if(bConfirm) { - if (CMainFrame::GetMainFrame()->MessageBox("Do you want to convert all instruments to samples ?\n", + if (CMainFrame::GetMainFrame()->MessageBox("Do you want to convert all instruments to samples?", "Removing all instruments", MB_YESNO | MB_ICONQUESTION) == IDYES) { m_pModDoc->ConvertInstrumentsToSamples(); } - - if (::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing all instruments", MB_YESNO | MB_ICONQUESTION) == IDYES) { - removeSamples = 1; - } } - if(removeSamples == -1) m_pModDoc->GetSampleUndo()->ClearUndo(); - - for (INSTRUMENTINDEX i = 1; i <= pSndFile->m_nInstruments; i++) + for (INSTRUMENTINDEX i = 1; i <= pSndFile->GetNumInstruments(); i++) { - pSndFile->DestroyInstrument(i, removeSamples); + pSndFile->DestroyInstrument(i, -1); } pSndFile->m_nInstruments = 0; Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-13 20:38:28 UTC (rev 854) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-14 14:23:39 UTC (rev 855) @@ -113,8 +113,10 @@ // -> CODE#0003 // -> DESC="remove instrument's samples" //rewbs: changed message - if(removeSamples > 0 || (removeSamples == 0 && ::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES)) + if(removeSamples > 0 || (removeSamples == 0 && ::MessageBox(NULL, "Remove samples associated with an instrument if it is unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES)) + { RemoveInstrumentSamples(nInstr); + } // -! BEHAVIOUR_CHANGE#0003 // -> CODE#0023 @@ -146,8 +148,7 @@ bool CSoundFile::RemoveInstrumentSamples(INSTRUMENTINDEX nInstr) //-------------------------------------------------------------- { - vector<bool> sampleused; - sampleused.resize(GetNumSamples() + 1, false); + vector<bool> sampleused(GetNumSamples() + 1, false); if (Instruments[nInstr]) { @@ -169,7 +170,7 @@ for (SAMPLEINDEX nSmp = 1; nSmp <= GetNumSamples(); nSmp++) if (sampleused[nSmp]) { DestroySample(nSmp); - m_szNames[nSmp][0] = 0; + strcpy(m_szNames[nSmp], ""); } return true; } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-13 20:38:28 UTC (rev 854) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-14 14:23:39 UTC (rev 855) @@ -2505,16 +2505,19 @@ #ifndef FASTSOUNDLIB -bool CSoundFile::IsSampleUsed(SAMPLEINDEX nSample) -//------------------------------------------------ +// Check whether a sample is used. +// In sample mode, the sample numbers in all patterns are checked. +// In instrument mode, it is only checked if a sample is referenced by an instrument (but not if the sample is actually played anywhere) +bool CSoundFile::IsSampleUsed(SAMPLEINDEX nSample) const +//------------------------------------------------------ { - if ((!nSample) || (nSample > m_nSamples)) return false; - if (m_nInstruments) + if ((!nSample) || (nSample > GetNumSamples())) return false; + if (GetNumInstruments()) { - for (UINT i=1; i<=m_nInstruments; i++) if (Instruments[i]) + for (UINT i = 1; i <= GetNumInstruments(); i++) if (Instruments[i]) { MODINSTRUMENT *pIns = Instruments[i]; - for (UINT j=0; j<128; j++) + for (UINT j = 0; j < CountOf(pIns->Keyboard); j++) { if (pIns->Keyboard[j] == nSample) return true; } @@ -2523,7 +2526,7 @@ { for (UINT i=0; i<Patterns.Size(); i++) if (Patterns[i]) { - MODCOMMAND *m = Patterns[i]; + const MODCOMMAND *m = Patterns[i]; for (UINT j=m_nChannels*Patterns[i].GetNumRows(); j; m++, j--) { if (m->instr == nSample && !m->IsPcNote()) return true; @@ -2534,13 +2537,13 @@ } -bool CSoundFile::IsInstrumentUsed(INSTRUMENTINDEX nInstr) -//------------------------------------------------------- +bool CSoundFile::IsInstrumentUsed(INSTRUMENTINDEX nInstr) const +//------------------------------------------------------------- { - if ((!nInstr) || (nInstr > m_nInstruments) || (!Instruments[nInstr])) return false; + if ((!nInstr) || (nInstr > GetNumInstruments()) || (!Instruments[nInstr])) return false; for (UINT i=0; i<Patterns.Size(); i++) if (Patterns[i]) { - MODCOMMAND *m = Patterns[i]; + const MODCOMMAND *m = Patterns[i]; for (UINT j=m_nChannels*Patterns[i].GetNumRows(); j; m++, j--) { if (m->instr == nInstr && !m->IsPcNote()) return true; @@ -2550,8 +2553,10 @@ } -SAMPLEINDEX CSoundFile::DetectUnusedSamples(vector<bool> &sampleUsed) -//------------------------------------------------------------------- +// Detect samples are are referenced by an instrument, but actually not used in a song. +// Only works in instrument mode. Unused samples are marked as false in the vector. +SAMPLEINDEX CSoundFile::DetectUnusedSamples(vector<bool> &sampleUsed) const +//------------------------------------------------------------------------- { sampleUsed.assign(GetNumSamples() + 1, false); @@ -2606,19 +2611,23 @@ } -bool CSoundFile::RemoveSelectedSamples(bool *pbIns) -//------------------------------------------------- +// Destroy samples where keepSamples index is false. First sample is keepSamples[1]! +SAMPLEINDEX CSoundFile::RemoveSelectedSamples(const vector<bool> &keepSamples) +//---------------------------------------------------------------------------- { - if (!pbIns) return false; - for (SAMPLEINDEX nSmp=1; nSmp<MAX_SAMPLES; nSmp++) + SAMPLEINDEX nRemoved = 0; + for (SAMPLEINDEX nSmp = (SAMPLEINDEX)min(MAX_SAMPLES - 1, keepSamples.size()); nSmp >= 1; nSmp--) { - if ((!pbIns[nSmp]) && (Samples[nSmp].pSample)) + if(!keepSamples[nSmp]) { - DestroySample(nSmp); - if ((nSmp == m_nSamples) && (nSmp > 1)) m_nSamples--; + if(DestroySample(nSmp)) + { + nRemoved++; + } + if((nSmp == GetNumSamples()) && (nSmp > 1)) m_nSamples--; } } - return true; + return nRemoved; } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-13 20:38:28 UTC (rev 854) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-14 14:23:39 UTC (rev 855) @@ -948,11 +948,11 @@ //BOOL DestroyInstrument(UINT nInstr); bool DestroyInstrument(INSTRUMENTINDEX nInstr, char removeSamples = 0); // -! BEHAVIOUR_CHANGE#0003 - bool IsSampleUsed(SAMPLEINDEX nSample); - bool IsInstrumentUsed(INSTRUMENTINDEX nInstr); + bool IsSampleUsed(SAMPLEINDEX nSample) const; + bool IsInstrumentUsed(INSTRUMENTINDEX nInstr) const; bool RemoveInstrumentSamples(INSTRUMENTINDEX nInstr); - SAMPLEINDEX DetectUnusedSamples(vector<bool> &sampleUsed); - bool RemoveSelectedSamples(bool *pbIns); + SAMPLEINDEX DetectUnusedSamples(vector<bool> &sampleUsed) const; + SAMPLEINDEX RemoveSelectedSamples(const vector<bool> &keepSamples); void AdjustSampleLoop(MODSAMPLE *pSmp); // Samples file I/O bool ReadSampleFromFile(SAMPLEINDEX nSample, LPBYTE lpMemFile, DWORD dwFileLength); Modified: trunk/OpenMPT/soundlib/modsmp_ctrl.cpp =================================================================== --- trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2011-04-13 20:38:28 UTC (rev 854) +++ trunk/OpenMPT/soundlib/modsmp_ctrl.cpp 2011-04-14 14:23:39 UTC (rev 855) @@ -226,6 +226,8 @@ switch(resetflag) { case SmpResetInit: + strcpy(rSndFile.m_szNames[i], ""); + strcpy(rSndFile.Samples[i].filename, ""); rSndFile.Samples[i].nC5Speed = 8363; // note: break is left out intentionally. keep this order or c&p the stuff from below if you change anything! case SmpResetCompo: @@ -411,7 +413,7 @@ template <class T> void UnsignSampleImpl(T* pStart, T nOffset, const SmpLength nLength) -//--------------------------------------------------------------------- +//------------------------------------------------------------------ { for(SmpLength i = 0; i < nLength; i++) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-17 14:15:55
|
Revision: 857 http://modplug.svn.sourceforge.net/modplug/?rev=857&view=rev Author: saga-games Date: 2011-04-17 14:15:48 +0000 (Sun, 17 Apr 2011) Log Message: ----------- [Ref] Made MODMIDICFG arrays two-dimensional (instead of one long string)... this makes macro handling look less weird. Modified Paths: -------------- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/mptrack/dlg_misc.h trunk/OpenMPT/soundlib/Sampleio.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h Modified: trunk/OpenMPT/mptrack/AbstractVstEditor.cpp =================================================================== --- trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/AbstractVstEditor.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -51,7 +51,7 @@ ON_MESSAGE(WM_MOD_KEYCOMMAND, OnCustomKeyMsg) //rewbs.customKeys ON_COMMAND_RANGE(ID_PLUGSELECT, ID_PLUGSELECT+MAX_MIXPLUGINS, OnToggleEditor) //rewbs.patPlugName ON_COMMAND_RANGE(ID_SELECTINST, ID_SELECTINST+MAX_INSTRUMENTS, OnSetInputInstrument) //rewbs.patPlugName - ON_COMMAND_RANGE(ID_LEARN_MACRO_FROM_PLUGGUI, ID_LEARN_MACRO_FROM_PLUGGUI+NMACROS, PrepareToLearnMacro) + ON_COMMAND_RANGE(ID_LEARN_MACRO_FROM_PLUGGUI, ID_LEARN_MACRO_FROM_PLUGGUI + NUM_MACROS, PrepareToLearnMacro) END_MESSAGE_MAP() CAbstractVstEditor::CAbstractVstEditor(CVstPlugin *pPlugin) @@ -246,7 +246,7 @@ void CAbstractVstEditor::OnMacroInfo() { //TODO /* - for (UINT m=0; m<NMACROS; m++) + for (UINT m=0; m<NUM_MACROS; m++) { } */ @@ -568,24 +568,28 @@ int macroType,nParam,action; CModDoc* pModDoc = m_pVstPlugin->GetModDoc(); - if (!pModDoc) { + if (!pModDoc) + { return; } CMenu* pInfoMenu = m_pMenu->GetSubMenu(2); pInfoMenu->DeleteMenu(2, MF_BYPOSITION); - if (m_pMacroMenu->m_hMenu) { + if (m_pMacroMenu->m_hMenu) + { m_pMacroMenu->DestroyMenu(); } - if (!m_pMacroMenu->m_hMenu) { + if (!m_pMacroMenu->m_hMenu) + { m_pMacroMenu->CreatePopupMenu(); } - for (int nMacro=0; nMacro<NMACROS; nMacro++) { + for (int nMacro=0; nMacro<NUM_MACROS; nMacro++) + { action=NULL; greyed=true; - macroText = &(pModDoc->GetSoundFile()->m_MidiCfg.szMidiSFXExt[nMacro*32]); + macroText = pModDoc->GetSoundFile()->m_MidiCfg.szMidiSFXExt[nMacro]; macroType = pModDoc->GetMacroType(macroText); switch (macroType) { @@ -790,8 +794,10 @@ //Then pModDoc->LearnMacro(macro, param) is called } -void CAbstractVstEditor::SetLearnMacro(int inMacro) { - if (inMacro<NMACROS) { +void CAbstractVstEditor::SetLearnMacro(int inMacro) +{ + if (inMacro < NUM_MACROS) + { m_nLearnMacro=inMacro; } } Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -2274,7 +2274,7 @@ case CMD_S3MCMDEX: if ((param & 0xF0) == 0xF0 && !(m_SndFile.m_nType & MOD_TYPE_MOD)) //Set Macro { - macroText = &m_SndFile.m_MidiCfg.szMidiSFXExt[(param & 0x0F) * 32]; + macroText = m_SndFile.m_MidiCfg.szMidiSFXExt[(param & 0x0F)]; chanSpec.Format(" to %d: ", param & 0x0F); } break; @@ -2282,7 +2282,7 @@ case CMD_SMOOTHMIDI: if (param < 0x80 && nChn != CHANNELINDEX_INVALID) { - macroText = &m_SndFile.m_MidiCfg.szMidiSFXExt[m_SndFile.Chn[nChn].nActiveMacro*32]; + macroText = m_SndFile.m_MidiCfg.szMidiSFXExt[m_SndFile.Chn[nChn].nActiveMacro]; chanSpec.Format(": currently %d: ", m_SndFile.Chn[nChn].nActiveMacro); } else @@ -3221,7 +3221,7 @@ } for (int macro = 0; macro < NUM_MACROS; macro++) { - CString macroString = &(pSndFile->m_MidiCfg.szMidiSFXExt[macro * 32]); + CString macroString = pSndFile->m_MidiCfg.szMidiSFXExt[macro]; if (GetMacroType(macroString) == sfx_plug && MacroToPlugParam(macroString) == param) { return macro; @@ -3232,20 +3232,20 @@ } // Retrieve Zxx (Z80-ZFF) type from current macro configuration -enmFixedMacroType CModDoc::GetZxxType(const CHAR (&szMidiZXXExt)[128 * 32]) -//------------------------------------------------------------------------- +enmFixedMacroType CModDoc::GetZxxType(const CHAR (&szMidiZXXExt)[128][MACRO_LENGTH]) +//---------------------------------------------------------------------------------- { // Compare with all possible preset patterns for(int i = 1; i < sfx_fixed_max; i++) { // Prepare pattern to compare - CHAR szPatterns[128 * 32]; + CHAR szPatterns[128][MACRO_LENGTH]; CreateZxxFromType(szPatterns, static_cast<enmFixedMacroType>(i)); bool bFound = true; for(int j = 0; j < 128; j++) { - if(strncmp(&szPatterns[j * 32], &szMidiZXXExt[j * 32], 32)) + if(strncmp(szPatterns[j], szMidiZXXExt[j], MACRO_LENGTH)) { bFound = false; break; @@ -3257,8 +3257,8 @@ } // Create Zxx (Z80 - ZFF) from one out of five presets -void CModDoc::CreateZxxFromType(CHAR (&szMidiZXXExt)[128 * 32], enmFixedMacroType iZxxType) -//----------------------------------------------------------------------------------------- +void CModDoc::CreateZxxFromType(CHAR (&szMidiZXXExt)[128][MACRO_LENGTH], enmFixedMacroType iZxxType) +//-------------------------------------------------------------------------------------------------- { for(int i = 0; i < 128; i++) { @@ -3266,30 +3266,30 @@ { case sfx_fixed_reso4Bit: // Type 1 - Z80 - Z8F controls resonance - if (i < 16) wsprintf(&szMidiZXXExt[i * 32], "F0F001%02X", i * 8); - else szMidiZXXExt[i * 32] = 0; + if (i < 16) wsprintf(szMidiZXXExt[i], "F0F001%02X", i * 8); + else strcpy(szMidiZXXExt[i], ""); break; case sfx_fixed_reso7Bit: // Type 2 - Z80 - ZFF controls resonance - wsprintf(&szMidiZXXExt[i * 32], "F0F001%02X", i); + wsprintf(szMidiZXXExt[i], "F0F001%02X", i); break; case sfx_fixed_cutoff: // Type 3 - Z80 - ZFF controls cutoff - wsprintf(&szMidiZXXExt[i * 32], "F0F000%02X", i); + wsprintf(szMidiZXXExt[i], "F0F000%02X", i); break; case sfx_fixed_mode: // Type 4 - Z80 - ZFF controls filter mode - wsprintf(&szMidiZXXExt[i * 32], "F0F002%02X", i); + wsprintf(szMidiZXXExt[i], "F0F002%02X", i); break; case sfx_fixed_resomode: // Type 5 - Z80 - Z9F controls resonance + filter mode - if (i < 16) wsprintf(&szMidiZXXExt[i * 32], "F0F001%02X", i * 8); - else if (i < 32) wsprintf(&szMidiZXXExt[i * 32], "F0F002%02X", (i - 16) * 8); - else szMidiZXXExt[i * 32] = 0; + if (i < 16) wsprintf(szMidiZXXExt[i], "F0F001%02X", i * 8); + else if (i < 32) wsprintf(szMidiZXXExt[i], "F0F002%02X", (i - 16) * 8); + else strcpy(szMidiZXXExt[i], ""); break; } } @@ -3307,7 +3307,7 @@ return false; } // SF0: Z00-Z7F controls cutoff - if(GetMacroType(&(pSndFile->m_MidiCfg.szMidiSFXExt[0])) != sfx_cutoff) + if(GetMacroType(pSndFile->m_MidiCfg.szMidiSFXExt[0]) != sfx_cutoff) { return false; } @@ -3319,7 +3319,7 @@ // All other parametered macros are unused for(size_t i = 1; i < NUM_MACROS; i++) { - if(GetMacroType(&(pSndFile->m_MidiCfg.szMidiSFXExt[i * 32])) != sfx_unused) + if(GetMacroType(pSndFile->m_MidiCfg.szMidiSFXExt[i]) != sfx_unused) { return false; } @@ -3666,14 +3666,15 @@ void CModDoc::LearnMacro(int macroToSet, long paramToUse) //------------------------------------------------------- { - if (macroToSet<0 || macroToSet>NMACROS) + if (macroToSet < 0 || macroToSet > NUM_MACROS) { return; } //if macro already exists for this param, alert user and return - for (int checkMacro=0; checkMacro<NMACROS; checkMacro++) { - CString macroText = &(GetSoundFile()->m_MidiCfg.szMidiSFXExt[checkMacro*32]); + for (int checkMacro=0; checkMacro < NUM_MACROS; checkMacro++) + { + CString macroText = GetSoundFile()->m_MidiCfg.szMidiSFXExt[checkMacro]; int macroType = GetMacroType(macroText); if (macroType==sfx_plug && MacroToPlugParam(macroText)==paramToUse) { @@ -3685,7 +3686,7 @@ } //set new macro - CHAR *pMacroToSet = &(GetSoundFile()->m_MidiCfg.szMidiSFXExt[macroToSet*32]); + CHAR *pMacroToSet = GetSoundFile()->m_MidiCfg.szMidiSFXExt[macroToSet]; if (paramToUse<128) { wsprintf(pMacroToSet, "F0F0%Xz",paramToUse+128); } else if (paramToUse<384) { Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/Moddoc.h 2011-04-17 14:15:48 UTC (rev 857) @@ -257,8 +257,8 @@ static enmParameteredMacroType GetMacroType(CString value); //rewbs.xinfo static int MacroToPlugParam(CString value); //rewbs.xinfo static int MacroToMidiCC(CString value); - static enmFixedMacroType GetZxxType(const CHAR (&szMidiZXXExt)[128 * 32]); - static void CreateZxxFromType(CHAR (&szMidiZXXExt)[128 * 32], enmFixedMacroType iZxxType); + static enmFixedMacroType GetZxxType(const CHAR (&szMidiZXXExt)[128][MACRO_LENGTH]); + static void CreateZxxFromType(CHAR (&szMidiZXXExt)[128][MACRO_LENGTH], enmFixedMacroType iZxxType); bool IsMacroDefaultSetupUsed() const; int FindMacroForParam(long param) const; Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -608,13 +608,13 @@ m_szConfigFileName[0] = 0; for (UINT i=0; i<MAX_DLS_BANKS; i++) gpDLSBanks[i] = NULL; // Default macro config - memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); - strcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF"); - strcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC"); - strcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v"); - strcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0"); - strcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); - strcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); + MemsetZero(m_MidiCfg); + strcpy(m_MidiCfg.szMidiGlb[MIDIOUT_START], "FF"); + strcpy(m_MidiCfg.szMidiGlb[MIDIOUT_STOP], "FC"); + strcpy(m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON], "9c n v"); + strcpy(m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF], "9c n 0"); + strcpy(m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM], "Cc p"); + strcpy(m_MidiCfg.szMidiSFXExt[0], "F0F000z"); CModDoc::CreateZxxFromType(m_MidiCfg.szMidiZXXExt, sfx_fixed_reso4Bit); } @@ -867,17 +867,17 @@ { CHAR s[64], snam[32]; wsprintf(snam, "SF%X", isfx); - GetPrivateProfileString("Zxx Macros", snam, &m_MidiCfg.szMidiSFXExt[isfx*32], s, sizeof(s), m_szConfigFileName); - s[31] = 0; - memcpy(&m_MidiCfg.szMidiSFXExt[isfx*32], s, 32); + GetPrivateProfileString("Zxx Macros", snam, m_MidiCfg.szMidiSFXExt[isfx], s, CountOf(s), m_szConfigFileName); + s[MACRO_LENGTH - 1] = 0; + memcpy(m_MidiCfg.szMidiSFXExt[isfx], s, MACRO_LENGTH); } for (UINT izxx=0; izxx<128; izxx++) { CHAR s[64], snam[32]; wsprintf(snam, "Z%02X", izxx|0x80); - GetPrivateProfileString("Zxx Macros", snam, &m_MidiCfg.szMidiZXXExt[izxx*32], s, sizeof(s), m_szConfigFileName); - s[31] = 0; - memcpy(&m_MidiCfg.szMidiZXXExt[izxx*32], s, 32); + GetPrivateProfileString("Zxx Macros", snam, m_MidiCfg.szMidiZXXExt[izxx], s, CountOf(s), m_szConfigFileName); + s[MACRO_LENGTH - 1] = 0; + memcpy(m_MidiCfg.szMidiZXXExt[izxx], s, MACRO_LENGTH); } // Parse command line for standard shell commands, DDE, file open @@ -997,7 +997,7 @@ { CHAR s[64], snam[32]; wsprintf(snam, "SF%X", isfx); - memcpy(s, &m_MidiCfg.szMidiSFXExt[isfx*32], 32); + memcpy(s, m_MidiCfg.szMidiSFXExt[isfx], MACRO_LENGTH); s[31] = 0; if (!WritePrivateProfileString("Zxx Macros", snam, s, m_szConfigFileName)) break; } @@ -1005,8 +1005,8 @@ { CHAR s[64], snam[32]; wsprintf(snam, "Z%02X", izxx|0x80); - memcpy(s, &m_MidiCfg.szMidiZXXExt[izxx*32], 32); - s[31] = 0; + memcpy(s, m_MidiCfg.szMidiZXXExt[izxx], MACRO_LENGTH); + s[MACRO_LENGTH - 1] = 0; if (!WritePrivateProfileString("Zxx Macros", snam, s, m_szConfigFileName)) break; } } Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -3184,7 +3184,7 @@ //Figure out which plug param (if any) is controllable using the active macro on this channel. long activePlugParam = -1; BYTE activeMacro = pSndFile->Chn[nChn].nActiveMacro; - CString activeMacroString = &(pSndFile->m_MidiCfg.szMidiSFXExt[activeMacro*32]); + CString activeMacroString = pSndFile->m_MidiCfg.szMidiSFXExt[activeMacro]; if (pModDoc->GetMacroType(activeMacroString) == sfx_plug) { activePlugParam = pModDoc->MacroToPlugParam(activeMacroString); Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -676,8 +676,8 @@ ON_CBN_SELCHANGE(IDC_MACROCC, OnCCChanged) ON_EN_CHANGE(IDC_EDIT1, OnSFxEditChanged) ON_EN_CHANGE(IDC_EDIT2, OnZxxEditChanged) - ON_COMMAND_RANGE(ID_PLUGSELECT, ID_PLUGSELECT+NMACROS-1, OnViewAllParams) //rewbs.patPlugName - ON_COMMAND_RANGE(ID_PLUGSELECT+NMACROS, ID_PLUGSELECT+NMACROS+NMACROS-1, OnSetSFx) //rewbs.patPlugName + ON_COMMAND_RANGE(ID_PLUGSELECT, ID_PLUGSELECT + NUM_MACROS - 1, OnViewAllParams) //rewbs.patPlugName + ON_COMMAND_RANGE(ID_PLUGSELECT + NUM_MACROS, ID_PLUGSELECT + NUM_MACROS + NUM_MACROS - 1, OnSetSFx) //rewbs.patPlugName END_MESSAGE_MAP() @@ -761,18 +761,18 @@ int offsetx=108, offsety=30, separatorx=4, separatory=2, height=18, widthMacro=30, widthVal=55, widthType=135, widthBtn=60; - for (UINT m=0; m<NMACROS; m++) + for (UINT m=0; m<NUM_MACROS; m++) { m_EditMacro[m].Create("", /*BS_FLAT |*/ WS_CHILD | WS_VISIBLE | WS_TABSTOP /*| WS_BORDER*/, - CRect(offsetx, offsety+m*(separatory+height), offsetx+widthMacro, offsety+m*(separatory+height)+height), this, ID_PLUGSELECT+NMACROS+m); + CRect(offsetx, offsety+m*(separatory+height), offsetx+widthMacro, offsety+m*(separatory+height)+height), this, ID_PLUGSELECT+NUM_MACROS+m); m_EditMacro[m].SetFont(GetFont()); m_EditMacroType[m].Create(ES_READONLY | WS_CHILD| WS_VISIBLE | WS_TABSTOP | WS_BORDER, - CRect(offsetx+separatorx+widthMacro, offsety+m*(separatory+height), offsetx+widthMacro+widthType, offsety+m*(separatory+height)+height), this, ID_PLUGSELECT+NMACROS+m); + CRect(offsetx+separatorx+widthMacro, offsety+m*(separatory+height), offsetx+widthMacro+widthType, offsety+m*(separatory+height)+height), this, ID_PLUGSELECT+NUM_MACROS+m); m_EditMacroType[m].SetFont(GetFont()); m_EditMacroValue[m].Create(ES_CENTER | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER, - CRect(offsetx+separatorx+widthType+widthMacro, offsety+m*(separatory+height), offsetx+widthMacro+widthType+widthVal, offsety+m*(separatory+height)+height), this, ID_PLUGSELECT+NMACROS+m); + CRect(offsetx+separatorx+widthType+widthMacro, offsety+m*(separatory+height), offsetx+widthMacro+widthType+widthVal, offsety+m*(separatory+height)+height), this, ID_PLUGSELECT+NUM_MACROS+m); m_EditMacroValue[m].SetFont(GetFont()); m_BtnMacroShowAll[m].Create("Show All...", WS_CHILD | WS_TABSTOP | WS_VISIBLE, @@ -807,21 +807,24 @@ UINT start, end, macroType; int selectedMacro=m_CbnSFx.GetCurSel(); - if (macro>=0 && macro<16) { + if (macro>=0 && macro<16) + { start=macro; end=macro; - } else { + } else + { start=0; - end=NMACROS; + end=NUM_MACROS; } - for (int m=0; m<NMACROS; m++) { + for (int m=0; m<NUM_MACROS; m++) + { //SFx s.Format("SF%X", m); m_EditMacro[m].SetWindowText(s); //Macro value: - CString macroText = &m_MidiCfg.szMidiSFXExt[m*32]; + CString macroText = m_MidiCfg.szMidiSFXExt[m]; m_EditMacroValue[m].SetWindowText(macroText); m_EditMacroValue[m].SetBackColor(m == selectedMacro ? RGB(200,200,225) : RGB(245,245,245) ); @@ -865,16 +868,16 @@ sfx_preset = m_CbnSFxPreset.GetCurSel(); if (sfx < 16) { ToggleBoxes(sfx_preset, sfx); - memcpy(s, &m_MidiCfg.szMidiSFXExt[sfx*32], 32); - s[31] = 0; + memcpy(s, m_MidiCfg.szMidiSFXExt[sfx], MACRO_LENGTH); + s[MACRO_LENGTH - 1] = 0; m_EditSFx.SetWindowText(s); } zxx = m_CbnZxx.GetCurSel(); if (zxx < 0x80) { - memcpy(s, &m_MidiCfg.szMidiZXXExt[zxx*32], 32); - s[31] = 0; + memcpy(s, m_MidiCfg.szMidiZXXExt[zxx], MACRO_LENGTH); + s[MACRO_LENGTH - 1] = 0; m_EditZxx.SetWindowText(s); } UpdateMacroList(); @@ -908,9 +911,10 @@ //---------------------------------- { UINT sfx = m_CbnSFx.GetCurSel(); - if (sfx < 16) { + if (sfx < 16) + { CString macroText; - memcpy(macroText.GetBuffer(32), &m_MidiCfg.szMidiSFXExt[sfx*32], 32); + memcpy(macroText.GetBuffer(32), m_MidiCfg.szMidiSFXExt[sfx], MACRO_LENGTH); int preset = m_pModDoc->GetMacroType(macroText); m_CbnSFxPreset.SetCurSel(preset); } @@ -926,7 +930,7 @@ if (sfx < 16) { - CHAR *pmacro = &m_MidiCfg.szMidiSFXExt[sfx*32]; + CHAR *pmacro = m_MidiCfg.szMidiSFXExt[sfx]; switch(sfx_preset) { case sfx_unused: pmacro[0] = 0; break; // unused @@ -959,22 +963,28 @@ void CMidiMacroSetup::OnSFxEditChanged() //-------------------------------------- { - CHAR s[32]; + CHAR s[MACRO_LENGTH]; UINT sfx = m_CbnSFx.GetCurSel(); if (sfx < 16) { memset(s, 0, sizeof(s)); - m_EditSFx.GetWindowText(s, 31); - s[31] = 0; - //Make all uppercase - _strupr(s); - //Replace Z with z. - char* zocc = strchr(s,'Z'); - if (zocc) zocc[0]='z'; + m_EditSFx.GetWindowText(s, MACRO_LENGTH - 1); + s[MACRO_LENGTH - 1] = 0; + // Fix letter case + for(size_t i = 0; i < MACRO_LENGTH; i++) + { + if(s[i] >= 'd' && s[i] <= 'f') // a,b,c have special meanings + { + s[i] = s[i] - 'a' + 'A'; + } else if(s[i] == 'N' || s[i] == 'V' || s[i] == 'U' || s[i] == 'X' || s[i] == 'Y' || s[i] == 'Z' || s[i] == 'P') + { + s[i] = s[i] - 'A' + 'a'; + } + } - memcpy(&m_MidiCfg.szMidiSFXExt[sfx*32], s, 32); - int sfx_preset = m_pModDoc->GetMacroType(&(m_MidiCfg.szMidiSFXExt[sfx*32])); - //int param = m_pModDoc->MacroToPlugParam(&(m_MidiCfg.szMidiSFXExt[sfx*32])); + memcpy(m_MidiCfg.szMidiSFXExt[sfx], s, MACRO_LENGTH); + int sfx_preset = m_pModDoc->GetMacroType(m_MidiCfg.szMidiSFXExt[sfx]); + //int param = m_pModDoc->MacroToPlugParam(m_MidiCfg.szMidiSFXExt[sfx]); m_CbnSFxPreset.SetCurSel(sfx_preset); ToggleBoxes(sfx_preset, sfx); @@ -991,15 +1001,15 @@ if (zxx < 128) { memset(s, 0, sizeof(s)); - m_EditZxx.GetWindowText(s, 31); - s[31] = 0; - memcpy(&m_MidiCfg.szMidiZXXExt[zxx*32], s, 32); + m_EditZxx.GetWindowText(s, MACRO_LENGTH - 1); + s[MACRO_LENGTH - 1] = 0; + memcpy(m_MidiCfg.szMidiZXXExt[zxx], s, MACRO_LENGTH); } } void CMidiMacroSetup::OnSetSFx(UINT id) { - m_CbnSFx.SetCurSel(id-(ID_PLUGSELECT+NMACROS)); + m_CbnSFx.SetCurSel(id-(ID_PLUGSELECT + NUM_MACROS)); OnSFxChanged(); } @@ -1010,7 +1020,7 @@ CString message, plugName, paramName, line; int sfx = id-ID_PLUGSELECT; - int param = m_pModDoc->MacroToPlugParam(&(m_MidiCfg.szMidiSFXExt[sfx*32])); + int param = m_pModDoc->MacroToPlugParam(m_MidiCfg.szMidiSFXExt[sfx]); CVstPlugin *pVstPlugin; char s[256]; message.Format("These are the parameters that can be controlled by macro SF%X:\n\n",sfx); @@ -1056,7 +1066,7 @@ AddPluginParameternamesToCombobox(m_CbnMacroParam, *pVstPlugin); m_CbnMacroParam.SetRedraw(TRUE); - int param = m_pModDoc->MacroToPlugParam(&(m_MidiCfg.szMidiSFXExt[m_CbnSFx.GetCurSel()*32])); + int param = m_pModDoc->MacroToPlugParam(m_MidiCfg.szMidiSFXExt[m_CbnSFx.GetCurSel()]); m_CbnMacroParam.SetCurSel(param); } //OnPlugParamChanged(); @@ -1095,7 +1105,7 @@ m_CbnMacroPlug.EnableWindow(TRUE); m_CbnMacroParam.EnableWindow(TRUE); SetDlgItemText(IDC_GENMACROLABEL, "Plug/Param"); - m_CbnMacroParam.SetCurSel(m_pModDoc->MacroToPlugParam(&(m_MidiCfg.szMidiSFXExt[sfx*32]))); + m_CbnMacroParam.SetCurSel(m_pModDoc->MacroToPlugParam(m_MidiCfg.szMidiSFXExt[sfx])); } else { m_CbnMacroPlug.EnableWindow(FALSE); m_CbnMacroParam.EnableWindow(FALSE); @@ -1107,7 +1117,7 @@ m_CbnMacroPlug.ShowWindow(FALSE); m_CbnMacroPlug.ShowWindow(FALSE); SetDlgItemText(IDC_GENMACROLABEL, "MIDI CC"); - m_CbnMacroCC.SetCurSel(m_pModDoc->MacroToMidiCC(&(m_MidiCfg.szMidiSFXExt[sfx*32]))); + m_CbnMacroCC.SetCurSel(m_pModDoc->MacroToMidiCC(m_MidiCfg.szMidiSFXExt[sfx])); } else { m_CbnMacroCC.EnableWindow(FALSE); } Modified: trunk/OpenMPT/mptrack/dlg_misc.h =================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.h 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/mptrack/dlg_misc.h 2011-04-17 14:15:48 UTC (rev 857) @@ -130,8 +130,6 @@ //////////////////////////////////////////////////////////////////////// // Midi Macros (Zxx) -#define NMACROS 16 - //class CColourEdit; #include "ColourEdit.h" @@ -149,8 +147,8 @@ protected: CComboBox m_CbnSFx, m_CbnSFxPreset, m_CbnZxx, m_CbnZxxPreset, m_CbnMacroPlug, m_CbnMacroParam, m_CbnMacroCC; CEdit m_EditSFx, m_EditZxx; - CColourEdit m_EditMacroValue[NMACROS], m_EditMacroType[NMACROS]; //rewbs.macroGUI - CButton m_EditMacro[NMACROS], m_BtnMacroShowAll[NMACROS]; + CColourEdit m_EditMacroValue[NUM_MACROS], m_EditMacroType[NUM_MACROS]; //rewbs.macroGUI + CButton m_EditMacro[NUM_MACROS], m_BtnMacroShowAll[NUM_MACROS]; CSoundFile *m_pSndFile; CModDoc *m_pModDoc; Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -113,7 +113,7 @@ // -> CODE#0003 // -> DESC="remove instrument's samples" //rewbs: changed message - if(removeSamples > 0 || (removeSamples == 0 && ::MessageBox(NULL, "Remove samples associated with an instrument if it is unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES)) + if(removeSamples > 0 || (removeSamples == 0 && ::MessageBox(NULL, "Remove samples associated with an instrument if they are unused?", "Removing instrument", MB_YESNO | MB_ICONQUESTION) == IDYES)) { RemoveInstrumentSamples(nInstr); } @@ -505,7 +505,7 @@ // xtra field if (pxh) { - if (m_nType > MOD_TYPE_S3M) + if (!(GetType() & (MOD_TYPE_MOD|MOD_TYPE_S3M))) { if (pxh->dwFlags & CHN_PINGPONGLOOP) pSmp->uFlags |= CHN_PINGPONGLOOP; if (pxh->dwFlags & CHN_SUSTAINLOOP) pSmp->uFlags |= CHN_SUSTAINLOOP; Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -2106,9 +2106,9 @@ if((cmd == CMD_MIDI) && !(m_dwSongFlags & SONG_FIRSTTICK)) break; if (param < 0x80) - ProcessMidiMacro(nChn, (cmd == CMD_SMOOTHMIDI), &m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro << 5], param); + ProcessMidiMacro(nChn, (cmd == CMD_SMOOTHMIDI), m_MidiCfg.szMidiSFXExt[pChn->nActiveMacro], param); else - ProcessMidiMacro(nChn, (cmd == CMD_SMOOTHMIDI), &m_MidiCfg.szMidiZXXExt[(param & 0x7F) << 5], 0); + ProcessMidiMacro(nChn, (cmd == CMD_SMOOTHMIDI), m_MidiCfg.szMidiZXXExt[(param & 0x7F)], 0); break; // IMF Commands Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-17 14:15:48 UTC (rev 857) @@ -925,14 +925,14 @@ void CSoundFile::ResetMidiCfg() //----------------------------- { - memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_START*32], "FF"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_STOP*32], "FC"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON*32], "9c n v"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF*32], "9c n 0"); - lstrcpy(&m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM*32], "Cc p"); - lstrcpy(&m_MidiCfg.szMidiSFXExt[0], "F0F000z"); - for (int iz=0; iz<16; iz++) wsprintf(&m_MidiCfg.szMidiZXXExt[iz*32], "F0F001%02X", iz*8); + MemsetZero(m_MidiCfg); + lstrcpy(m_MidiCfg.szMidiGlb[MIDIOUT_START], "FF"); + lstrcpy(m_MidiCfg.szMidiGlb[MIDIOUT_STOP], "FC"); + lstrcpy(m_MidiCfg.szMidiGlb[MIDIOUT_NOTEON], "9c n v"); + lstrcpy(m_MidiCfg.szMidiGlb[MIDIOUT_NOTEOFF], "9c n 0"); + lstrcpy(m_MidiCfg.szMidiGlb[MIDIOUT_PROGRAM], "Cc p"); + lstrcpy(m_MidiCfg.szMidiSFXExt[0], "F0F000z"); + for (int iz=0; iz<16; iz++) wsprintf(m_MidiCfg.szMidiZXXExt[iz], "F0F001%02X", iz*8); } Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-17 12:26:43 UTC (rev 856) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-17 14:15:48 UTC (rev 857) @@ -447,11 +447,12 @@ #define NUM_MACROS 16 // number of parametered macros +#define MACRO_LENGTH 32 // max number of chars per macro struct MODMIDICFG { - CHAR szMidiGlb[9*32]; - CHAR szMidiSFXExt[16*32]; - CHAR szMidiZXXExt[128*32]; + CHAR szMidiGlb[9][MACRO_LENGTH]; + CHAR szMidiSFXExt[16][MACRO_LENGTH]; + CHAR szMidiZXXExt[128][MACRO_LENGTH]; }; typedef MODMIDICFG* LPMODMIDICFG; STATIC_ASSERT(sizeof(MODMIDICFG) == 4896); // this is directly written to files, so the size must be correct! @@ -654,7 +655,7 @@ UINT m_nMaxOrderPosition, m_nPatternNames; LPSTR m_lpszSongComments, m_lpszPatternNames; UINT ChnMix[MAX_CHANNELS]; // Channels to be mixed - MODCHANNEL Chn[MAX_CHANNELS]; // Mixing channels + MODCHANNEL Chn[MAX_CHANNELS]; // Mixing channels... First m_nChannel channels are master channels (i.e. they are never NNA channels)! MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; // Initial channels settings CPatternContainer Patterns; // Patterns ModSequenceSet Order; // Modsequences. Order[x] returns an index of a pattern located at order x of the current sequence. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-04-29 21:32:36
|
Revision: 860 http://modplug.svn.sourceforge.net/modplug/?rev=860&view=rev Author: saga-games Date: 2011-04-29 21:32:29 +0000 (Fri, 29 Apr 2011) Log Message: ----------- [Fix] Orderlist info text truncates order list length after first "---" pattern for MOD files in hex display mode as well. [Fix] "+++" separator patterns were allowed in MOD files, which made them break in other trackers / players. [Fix] MIDI Macros are now sanitized when being loaded from files (malicious macros didn't seem to result in crashes, but let's be safe here) [Ref] Some more refactoring Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/mptrack/Draw_pat.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/View_pat.h trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_itp.cpp trunk/OpenMPT/soundlib/Load_mod.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sampleio.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/mod_specifications.h Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -711,21 +711,22 @@ //------------------------------- { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); - if ((pMainFrm) && (m_pModDoc) && (::GetFocus() == m_hWnd)) + CSoundFile *pSndFile; + if ((pMainFrm != nullptr) && (m_pModDoc != nullptr) && (pSndFile = m_pModDoc->GetSoundFile()) != nullptr && (::GetFocus() == m_hWnd)) { CHAR s[128]; - CSoundFile *pSndFile = m_pModDoc->GetSoundFile(); + strcpy(s, ""); - s[0] = 0; + // MOD orderlist always ends after first empty pattern + const ORDERINDEX nLength = (pSndFile->GetType() & MOD_TYPE_MOD) ? pSndFile->Order.GetLengthFirstEmpty() : pSndFile->Order.GetLengthTailTrimmed(); + if(CMainFrame::m_dwPatternSetup & PATTERN_HEXDISPLAY) { - wsprintf(s, "Position %02Xh of %02Xh", m_nScrollPos, pSndFile->Order.GetLengthTailTrimmed()); + wsprintf(s, "Position %02Xh of %02Xh", m_nScrollPos, nLength); } else { - const ORDERINDEX nLength = pSndFile->Order.GetLengthTailTrimmed(); - wsprintf(s, "Position %d of %d (%02Xh of %02Xh)", - m_nScrollPos, nLength, m_nScrollPos, nLength); + wsprintf(s, "Position %d of %d (%02Xh of %02Xh)", m_nScrollPos, nLength, m_nScrollPos, nLength); } if (m_nScrollPos < pSndFile->Order.GetLength()) Modified: trunk/OpenMPT/mptrack/Draw_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Draw_pat.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/mptrack/Draw_pat.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -860,7 +860,9 @@ tx_col = MODCOLOR_TEXTSELECTED; bk_col = MODCOLOR_BACKSELECTED; } - if ((!*((LPDWORD)m)) && (!*(((LPWORD)m)+2)) && ((!col_sel) || (col_sel == 0x1F))) + // Speedup: Empty command which is either not or fully selected + //if ((!*((LPDWORD)m)) && (!*(((LPWORD)m)+2)) && ((!col_sel) || (col_sel == 0x1F))) + if (m->IsEmpty() && ((!col_sel) || (col_sel == 0x1F))) { m_Dib.SetTextColor(tx_col, bk_col); m_Dib.TextBlt(xbmp, 0, nColumnWidth-4, m_szCell.cy, pfnt->nClrX, pfnt->nClrY); @@ -875,7 +877,7 @@ if ((CMainFrame::m_dwPatternSetup & PATTERN_EFFECTHILIGHT) && (m->note) && (m->note <= NOTE_MAX)) { tx_col = MODCOLOR_NOTE; - // Highlight notes that are not supported by the Amiga + // Highlight notes that are not supported by the Amiga (for S3M this is not always correct) if((pSndFile->m_dwSongFlags & (SONG_PT1XMODE|SONG_AMIGALIMITS)) && (m->note < NOTE_MIDDLEC - 12 || m->note >= NOTE_MIDDLEC + 2 * 12)) tx_col = MODCOLOR_DODGY_COMMANDS; } @@ -1187,11 +1189,13 @@ if (m_nMidRow) sizeTotal.cy += m_nMidRow * m_szCell.cy * 2; SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine); //UpdateScrollPos(); //rewbs.FixLPsOddScrollingIssue - if (rect.Height() >= sizeTotal.cy) { - m_bWholePatternFitsOnScreen=true; + if (rect.Height() >= sizeTotal.cy) + { + m_bWholePatternFitsOnScreen = true; m_nYScroll = 0; //rewbs.fix2977 - } else { - m_bWholePatternFitsOnScreen=false; + } else + { + m_bWholePatternFitsOnScreen = false; } } } @@ -1450,7 +1454,7 @@ CSoundFile *pSndFile = pModDoc->GetSoundFile(); CHAR s[512]; UINT nChn; - wsprintf(s, "Row %d, Col %d", GetCurrentRow(), GetCurrentChannel()+1); + wsprintf(s, "Row %d, Col %d", GetCurrentRow(), GetCurrentChannel() + 1); pMainFrm->SetUserText(s); if (::GetFocus() == m_hWnd) { @@ -1464,12 +1468,12 @@ switch (GetColTypeFromCursor(m_dwCursor)) { - case 0: + case NOTE_COLUMN: // display note if(m->note >= NOTE_MIN_SPECIAL) strcpy(s, szSpecialNoteShortDesc[m->note - NOTE_MIN_SPECIAL]); break; - case 1: + case INST_COLUMN: // display instrument if (m->instr) { @@ -1485,9 +1489,9 @@ } else { // "normal" instrument - if (pSndFile->m_nInstruments) + if (pSndFile->GetNumInstruments()) { - if ((m->instr <= pSndFile->m_nInstruments) && (pSndFile->Instruments[m->instr])) + if ((m->instr <= pSndFile->GetNumInstruments()) && (pSndFile->Instruments[m->instr])) { MODINSTRUMENT *pIns = pSndFile->Instruments[m->instr]; memcpy(sztmp, pIns->name, 32); @@ -1495,7 +1499,7 @@ if ((m->note) && (m->note <= NOTE_MAX)) { UINT nsmp = pIns->Keyboard[m->note-1]; - if ((nsmp) && (nsmp <= pSndFile->m_nSamples)) + if ((nsmp) && (nsmp <= pSndFile->GetNumSamples())) { CHAR sztmp2[64] = ""; memcpy(sztmp2, pSndFile->m_szNames[nsmp], MAX_SAMPLENAME); @@ -1509,7 +1513,7 @@ } } else { - if (m->instr <= pSndFile->m_nSamples) + if (m->instr <= pSndFile->GetNumSamples()) { memcpy(sztmp, pSndFile->m_szNames[m->instr], MAX_SAMPLENAME); sztmp[32] = 0; @@ -1520,7 +1524,7 @@ if (sztmp[0]) wsprintf(s, "%d: %s", m->instr, sztmp); } break; - case 2: + case VOL_COLUMN: // display volume command if(m->IsPcNote()) { @@ -1538,8 +1542,8 @@ if (!pModDoc->GetVolCmdInfo(pModDoc->GetIndexFromVolCmd(m->volcmd), s)) s[0] = 0; } break; - case 3: - case 4: + case EFFECT_COLUMN: + case PARAM_COLUMN: // display effect command if(!m->IsPcNote()) { Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -3153,9 +3153,11 @@ //end rewbs.fix3185 //ensure order correlates with pattern. - if (pSndFile->Order[ord]!=pat) { + if (pSndFile->Order[ord]!=pat) + { ORDERINDEX tentativeOrder = pSndFile->FindOrder(pat); - if (tentativeOrder != ORDERINDEX_INVALID) { //ensure a valid order exists. + if (tentativeOrder != ORDERINDEX_INVALID) //ensure a valid order exists. + { ord = tentativeOrder; } } @@ -3192,11 +3194,13 @@ if ((param[1] >= '0') && (param[1] <= '9')) code += (param[1] - '0'); else if ((param[1] >= 'A') && (param[1] <= 'F')) code += (param[1] - 'A' + 0x0A); - if (macro.GetLength()>=4 && macro.GetAt(3)=='0') + if (macro.GetLength() >= 4 && macro.GetAt(3) == '0') return (code - 128); else return (code + 128); } + + int CModDoc::MacroToMidiCC(CString macro) //--------------------------------------- { @@ -3211,6 +3215,7 @@ return code; } + int CModDoc::FindMacroForParam(long param) const //---------------------------------------------- { @@ -3231,6 +3236,7 @@ return -1; } + // Retrieve Zxx (Z80-ZFF) type from current macro configuration enmFixedMacroType CModDoc::GetZxxType(const CHAR (&szMidiZXXExt)[128][MACRO_LENGTH]) //---------------------------------------------------------------------------------- @@ -3256,6 +3262,7 @@ return sfx_fixed_custom; // Custom setup } + // Create Zxx (Z80 - ZFF) from one out of five presets void CModDoc::CreateZxxFromType(CHAR (&szMidiZXXExt)[128][MACRO_LENGTH], enmFixedMacroType iZxxType) //-------------------------------------------------------------------------------------------------- @@ -3306,6 +3313,9 @@ { return false; } + // Global macros + // TODO + // SF0: Z00-Z7F controls cutoff if(GetMacroType(pSndFile->m_MidiCfg.szMidiSFXExt[0]) != sfx_cutoff) { Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -155,7 +155,6 @@ { memset(ChnVUMeters, 0, sizeof(ChnVUMeters)); memset(OldVUMeters, 0, sizeof(OldVUMeters)); - memset(MultiRecordMask, 0, sizeof(MultiRecordMask)); // -> CODE#0012 // -> DESC="midi keyboard split" memset(splitActiveNoteChannel, 0xFF, sizeof(splitActiveNoteChannel)); @@ -2260,9 +2259,9 @@ if (((pMainFrm->GetFollowSong(pModDoc) != m_hWnd) || (pSndFile->IsPaused()) || (!(m_dwStatus & PATSTATUS_FOLLOWSONG)))) { - DWORD sel = m_dwCursor | (m_nRow << 16); - InvalidateArea(sel, sel+5); //rewbs.fix3010 (no refresh under on last row) - SetCurrentRow(m_nRow+m_nSpacing); + DWORD sel = (nChn << 3) | (m_nRow << 16); + InvalidateArea(sel, sel + LAST_COLUMN); + SetCurrentRow(m_nRow + m_nSpacing); sel = m_dwCursor | (m_nRow << 16); SetCurSel(sel, sel); } @@ -2569,7 +2568,7 @@ if ((pModDoc = GetDocument()) == NULL || !(IsEditingEnabled_bmsg())) return; pSndFile = pModDoc->GetSoundFile(); - nChannels = pSndFile->m_nChannels; + nChannels = pSndFile->GetNumChannels(); nRows = pSndFile->Patterns[m_nPattern].GetNumRows(); pOldPattern = pSndFile->Patterns[m_nPattern]; if ((nChannels < 1) || (nRows < 1) || (!pOldPattern)) return; @@ -3978,7 +3977,7 @@ if(oldcmd != *p) { pModDoc->SetModified(); - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); } } @@ -4053,7 +4052,7 @@ if(oldcmd != *p) { pModDoc->SetModified(); - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); } } // end if mainframe & moddoc exist @@ -4100,7 +4099,7 @@ if(*p != oldcmd) { pModDoc->SetModified(); - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); } } @@ -4234,7 +4233,7 @@ if(bIsLiveRecord == false) { DWORD sel = (nRow << 16) | (nChn << 3); - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); } @@ -4314,7 +4313,7 @@ if(*p != oldcmd) { pModDoc->SetModified(); - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); } } @@ -4372,7 +4371,7 @@ pSndFile->Patterns[m_nPattern].GetpModCommand(nRow, nChn)->note = note; const DWORD sel = (nRow << 16) | m_dwCursor; pModDoc->SetModified(); - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); return; } @@ -4521,7 +4520,7 @@ pModDoc->SetModified(); if(bIsLiveRecord == false) { // Update only when not recording live. - InvalidateArea(sel, sel+5); + InvalidateArea(sel, sel + LAST_COLUMN); UpdateIndicator(); } } Modified: trunk/OpenMPT/mptrack/View_pat.h =================================================================== --- trunk/OpenMPT/mptrack/View_pat.h 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/mptrack/View_pat.h 2011-04-29 21:32:29 UTC (rev 860) @@ -54,7 +54,7 @@ LAST_COLUMN = PARAM_COLUMN }; -static_assert(MAX_CHANNELS <= 0x1FFF, "Check: Channel index in pattern editor is only 13 bits wide!"); +static_assert(MAX_BASECHANNELS <= 0x1FFF, "Check: Channel index in pattern editor is only 13 bits wide!"); //Struct for controlling selection clearing. This is used to define which data fields @@ -117,7 +117,6 @@ WORD ChnVUMeters[MAX_BASECHANNELS]; WORD OldVUMeters[MAX_BASECHANNELS]; CListBox *ChnEffectList[MAX_BASECHANNELS]; //rewbs.patPlugName - BYTE MultiRecordMask[(MAX_CHANNELS+7)/8]; UINT m_nFoundInstrument; UINT m_nMenuOnChan; DWORD m_dwLastNoteEntryTime; //rewbs.customkeys Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -234,11 +234,11 @@ static inline UINT ConvertVolParam(UINT value) //-------------------------------------------- { - return (value > 9) ? 9 : value; + return (value > 9) ? 9 : value; } -// Convert MPT's internal nvelope format into an IT/MPTM envelope. +// Convert MPT's internal envelope format into an IT/MPTM envelope. void MPTEnvToIT(const INSTRUMENTENVELOPE *mptEnv, ITENVELOPE *itEnv, const BYTE envOffset, const BYTE envDefault) //--------------------------------------------------------------------------------------------------------------- { @@ -795,7 +795,8 @@ { if (dwMemPos + sizeof(MODMIDICFG) < dwMemLength) { - memcpy(&m_MidiCfg, lpStream+dwMemPos, sizeof(MODMIDICFG)); + memcpy(&m_MidiCfg, lpStream + dwMemPos, sizeof(MODMIDICFG)); + SanitizeMacros(); dwMemPos += sizeof(MODMIDICFG); } } @@ -1173,7 +1174,7 @@ { m[ch].volcmd = VOLCMD_VIBRATODEPTH; m[ch].vol = vol - 203; // Old versions of ModPlug saved this as vibrato speed instead, so let's fix that - if(m_dwLastSavedWithVersion <= MAKE_VERSION_NUMERIC(1, 17, 02, 54) && interpretModPlugMade) + if(m_dwLastSavedWithVersion && m_dwLastSavedWithVersion <= MAKE_VERSION_NUMERIC(1, 17, 02, 54)) m[ch].volcmd = VOLCMD_VIBRATOSPEED; } else // 213-222: Unused (was velocity) @@ -1348,7 +1349,7 @@ ITFILEHEADER header; ITINSTRUMENT iti; ITSAMPLESTRUCT itss; - BYTE smpcount[(MAX_SAMPLES+7)/8]; + vector<bool>smpcount(GetNumSamples(), false); DWORD inspos[MAX_INSTRUMENTS]; vector<DWORD> patpos; DWORD smppos[MAX_SAMPLES]; @@ -1539,7 +1540,6 @@ if (Instruments[nins]) { MODINSTRUMENT *pIns = Instruments[nins]; - memset(smpcount, 0, sizeof(smpcount)); memcpy(iti.filename, pIns->filename, 12); memcpy(iti.name, pIns->name, 26); iti.mbank = pIns->wMidiBank; @@ -1570,10 +1570,10 @@ iti.nos = 0; for (UINT i=0; i<NOTE_MAX; i++) if (pIns->Keyboard[i] < MAX_SAMPLES) { - UINT smp = pIns->Keyboard[i]; - if ((smp) && (!(smpcount[smp>>3] & (1<<(smp&7))))) + const UINT smp = pIns->Keyboard[i]; + if (smp && !smpcount[smp - 1]) { - smpcount[smp>>3] |= 1 << (smp&7); + smpcount[smp - 1] = true; iti.nos++; } iti.keyboard[i*2] = (pIns->NoteMap[i] >= NOTE_MIN && pIns->NoteMap[i] <= NOTE_MAX) ? (pIns->NoteMap[i] - 1) : i; @@ -1978,7 +1978,7 @@ ITFILEHEADER header; ITINSTRUMENT iti; ITSAMPLESTRUCT itss; - BYTE smpcount[(MAX_SAMPLES+7)/8]; + vector<bool>smpcount(GetNumSamples(), false); DWORD inspos[MAX_INSTRUMENTS]; DWORD patpos[MAX_PATTERNS]; DWORD smppos[MAX_SAMPLES]; @@ -2142,7 +2142,6 @@ if (Instruments[nins]) { MODINSTRUMENT *pIns = Instruments[nins]; - memset(smpcount, 0, sizeof(smpcount)); memcpy(iti.filename, pIns->filename, 12); memcpy(iti.name, pIns->name, 26); SetNullTerminator(iti.name); @@ -2165,10 +2164,10 @@ iti.nos = 0; for (UINT i=0; i<NOTE_MAX; i++) if (pIns->Keyboard[i] < MAX_SAMPLES) { - UINT smp = pIns->Keyboard[i]; - if ((smp) && (!(smpcount[smp>>3] & (1<<(smp&7))))) + const UINT smp = pIns->Keyboard[i]; + if (smp && !smpcount[smp - 1]) { - smpcount[smp>>3] |= 1 << (smp&7); + smpcount[smp - 1] = true; iti.nos++; } iti.keyboard[i*2] = (pIns->NoteMap[i] >= NOTE_MIN && pIns->NoteMap[i] <= NOTE_MAX) ? (pIns->NoteMap[i] - 1) : i; Modified: trunk/OpenMPT/soundlib/Load_itp.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_itp.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Load_itp.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -172,8 +172,10 @@ // midi cfg ASSERT_CAN_READ(id); - if (id<=sizeof(m_MidiCfg)) { - memcpy(&m_MidiCfg,lpStream+dwMemPos,id); + if (id <= sizeof(m_MidiCfg)) + { + memcpy(&m_MidiCfg, lpStream + dwMemPos, id); + SanitizeMacros(); dwMemPos += id; } Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -617,7 +617,7 @@ UINT nbp = 0, norders = 128; for (UINT iord=0; iord<128; iord++) { - if (Order[iord] == Order.GetInvalidPatIndex()) + if (Order[iord] == Order.GetInvalidPatIndex() || Order[iord] == Order.GetIgnoreIndex()) { norders = iord; break; @@ -644,7 +644,8 @@ } fwrite(bTab, 4, 1, f); // Writing patterns - for (UINT ipat=0; ipat<nbp; ipat++) { //for all patterns + for (UINT ipat=0; ipat<nbp; ipat++) //for all patterns + { BYTE s[64*4]; if (Patterns[ipat]) //if pattern exists { Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -615,7 +615,8 @@ dwMemPos += 8; if (len == sizeof(MODMIDICFG)) { - memcpy(&m_MidiCfg, lpStream+dwMemPos, len); + memcpy(&m_MidiCfg, lpStream + dwMemPos, len); + SanitizeMacros(); m_dwSongFlags |= SONG_EMBEDMIDICFG; dwMemPos += len; //rewbs.fix36946 } Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -1787,14 +1787,14 @@ ITINSTRUMENT *iti = (ITINSTRUMENT *)buffer; ITSAMPLESTRUCT itss; MODINSTRUMENT *pIns = Instruments[nInstr]; - UINT smpcount[MAX_SAMPLES], smptable[MAX_SAMPLES], smpmap[MAX_SAMPLES]; + vector<bool> smpcount(GetNumSamples(), false); + UINT smptable[MAX_SAMPLES], smpmap[MAX_SAMPLES]; DWORD dwPos; FILE *f; if ((!pIns) || (!lpszFileName)) return false; if ((f = fopen(lpszFileName, "wb")) == NULL) return false; memset(buffer, 0, sizeof(buffer)); - memset(smpcount, 0, sizeof(smpcount)); memset(smptable, 0, sizeof(smptable)); memset(smpmap, 0, sizeof(smpmap)); iti->id = LittleEndian(IT_IMPI); // "IMPI" @@ -1822,10 +1822,10 @@ iti->nos = 0; for (UINT i=0; i<NOTE_MAX; i++) if (pIns->Keyboard[i] < MAX_SAMPLES) { - UINT smp = pIns->Keyboard[i]; - if ((smp) && (!smpcount[smp])) + const UINT smp = pIns->Keyboard[i]; + if (smp && !smpcount[smp - 1]) { - smpcount[smp] = 1; + smpcount[smp - 1] = true; smptable[iti->nos] = smp; smpmap[smp] = iti->nos; iti->nos++; Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp =================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -3965,10 +3965,10 @@ } -UINT __cdecl CSoundFile::GetChannelPlugin(UINT nChn, bool respectMutes) -//-------------------------------------------------------------- +UINT __cdecl CSoundFile::GetChannelPlugin(UINT nChn, bool respectMutes) const +//--------------------------------------------------------------------------- { - MODCHANNEL *pChn= &Chn[nChn]; + const MODCHANNEL *pChn = &Chn[nChn]; // If it looks like this is an NNA channel, we need to find the master channel. // This ensures we pick up the right ChnSettings. @@ -3988,10 +3988,10 @@ } -UINT CSoundFile::GetActiveInstrumentPlugin(UINT nChn, bool respectMutes) -//----------------------------------------------------------------------- +UINT CSoundFile::GetActiveInstrumentPlugin(UINT nChn, bool respectMutes) const +//---------------------------------------------------------------------------- { - MODCHANNEL *pChn = &Chn[nChn]; + const MODCHANNEL *pChn = &Chn[nChn]; // Unlike channel settings, pModInstrument is copied from the original chan to the NNA chan, // so we don't nee to worry about finding the master chan. @@ -4007,8 +4007,8 @@ } -UINT CSoundFile::GetBestMidiChan(MODCHANNEL *pChn) -//------------------------------------------------ +UINT CSoundFile::GetBestMidiChan(const MODCHANNEL *pChn) const +//------------------------------------------------------------ { if (pChn && pChn->pModInstrument && pChn->pModInstrument->nMidiChannel) { Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-04-29 21:32:29 UTC (rev 860) @@ -936,6 +936,25 @@ } +// Set null terminator for all MIDI macros +void CSoundFile::SanitizeMacros() +//------------------------------- +{ + for(size_t i = 0; i < CountOf(m_MidiCfg.szMidiGlb); i++) + { + SetNullTerminator(m_MidiCfg.szMidiGlb[i]); + } + for(size_t i = 0; i < CountOf(m_MidiCfg.szMidiSFXExt); i++) + { + SetNullTerminator(m_MidiCfg.szMidiSFXExt[i]); + } + for(size_t i = 0; i < CountOf(m_MidiCfg.szMidiZXXExt); i++) + { + SetNullTerminator(m_MidiCfg.szMidiZXXExt[i]); + } +} + + BOOL CSoundFile::SetWaveConfig(UINT nRate,UINT nBits,UINT nChannels,BOOL bMMX) //---------------------------------------------------------------------------- { @@ -2620,7 +2639,7 @@ return 0; } SAMPLEINDEX nRemoved = 0; - for (SAMPLEINDEX nSmp = (SAMPLEINDEX)min(GetNumSamples(), keepSamples.size() - 1); nSmp >= 1; nSmp--) + for(SAMPLEINDEX nSmp = (SAMPLEINDEX)min(GetNumSamples(), keepSamples.size() - 1); nSmp >= 1; nSmp--) { if(!keepSamples[nSmp]) { Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-04-29 21:32:29 UTC (rev 860) @@ -433,7 +433,9 @@ //////////////////////////////////////////////////////////////////// -enum { +// Global MIDI macros +enum +{ MIDIOUT_START=0, MIDIOUT_STOP, MIDIOUT_TICK, @@ -454,7 +456,6 @@ CHAR szMidiSFXExt[16][MACRO_LENGTH]; CHAR szMidiZXXExt[128][MACRO_LENGTH]; }; -typedef MODMIDICFG* LPMODMIDICFG; STATIC_ASSERT(sizeof(MODMIDICFG) == 4896); // this is directly written to files, so the size must be correct! typedef VOID (__cdecl * LPSNDMIXHOOKPROC)(int *, unsigned long, unsigned long); // buffer, samples, channels @@ -990,6 +991,7 @@ // Misc functions MODSAMPLE *GetSample(UINT n) { return Samples+n; } void ResetMidiCfg(); + void SanitizeMacros(); UINT MapMidiInstrument(DWORD dwProgram, UINT nChannel, UINT nNote); long ITInstrToMPT(const void *p, MODINSTRUMENT *pIns, UINT trkvers); //change from BOOL for rewbs.modularInstData UINT LoadMixPlugins(const void *pData, UINT nLen); @@ -1051,9 +1053,9 @@ void resetEnvelopes(MODCHANNEL* pChn, enmResetEnv envToReset = ENV_RESET_ALL); void SetDefaultInstrumentValues(MODINSTRUMENT *pIns); private: - UINT __cdecl GetChannelPlugin(UINT nChan, bool respectMutes); - UINT __cdecl GetActiveInstrumentPlugin(UINT nChan, bool respectMutes); - UINT GetBestMidiChan(MODCHANNEL *pChn); + UINT __cdecl GetChannelPlugin(UINT nChan, bool respectMutes) const; + UINT __cdecl GetActiveInstrumentPlugin(UINT nChan, bool respectMutes) const; + UINT GetBestMidiChan(const MODCHANNEL *pChn) const; void HandlePatternTransitionEvents(); void BuildDefaultInstrument(); Modified: trunk/OpenMPT/soundlib/mod_specifications.h =================================================================== --- trunk/OpenMPT/soundlib/mod_specifications.h 2011-04-19 20:43:50 UTC (rev 859) +++ trunk/OpenMPT/soundlib/mod_specifications.h 2011-04-29 21:32:29 UTC (rev 860) @@ -178,7 +178,7 @@ false, // No envelope release node " 0123456789ABCD?FF?E???????????????", // Supported Effects " ???????????????", // Supported Volume Column commands - true, // Has "+++" pattern + false, // Doesn't have "+++" pattern true, // Has restart position (order) false, // Doesn't support plugins false, // No custom pattern time signatures @@ -257,7 +257,7 @@ false, // No envelope release node " 0123456789ABCDRFFTE???GHK?YXPLZ\\?#", // Supported Effects " vpcdabuhlrgfe?o", // Supported Volume Column commands - true, // Has "+++" pattern + false, // Doesn't have "+++" pattern true, // Has restart position (order) true, // Supports plugins false, // No custom pattern time signatures This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-05-02 17:40:22
|
Revision: 861 http://modplug.svn.sourceforge.net/modplug/?rev=861&view=rev Author: saga-games Date: 2011-05-02 17:40:15 +0000 (Mon, 02 May 2011) Log Message: ----------- [Fix] 8SVX Loader: If no sample could be found in the file, the loader does not claim to have successfully loaded a sample anymore. [Mod] Updated History.txt Modified Paths: -------------- trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/soundlib/Sampleio.cpp Modified: trunk/OpenMPT/packageTemplate/History.txt =================================================================== --- trunk/OpenMPT/packageTemplate/History.txt 2011-04-29 21:32:29 UTC (rev 860) +++ trunk/OpenMPT/packageTemplate/History.txt 2011-05-02 17:40:15 UTC (rev 861) @@ -10,12 +10,13 @@ (tx XYZ): thanks to XYZ for telling us about the bug / requesting the feature -v1.19.02.00 (***** 2011, revision 848) +v1.19.02.00 (***** 2011, revision 861) -------------------------------------- Pattern tab::Note properties [New] <Jojo> Channels can now be moved by dragging their channel header. Holding Shift while doing so duplicates the channel [Imp] <Jojo> Moving channels through the channel manager creates an undo point now. [Fix] <Jojo> Axx is not limited to value 7F anymore in IT / S3M format. + [Fix] <Jojo> Order list info text now truncates list length after the first "---" pattern for MOD files in hex display mode as well. VST [New] <Jojo> New menu entry in the plugin editor: Create instrument from plugin @@ -23,17 +24,28 @@ Mod Conversion [Imp] <Jojo> Improved conversion of Sxx (IT / S3M) and PC Notes. + [Mod] <Jojo> When converting from MOD/S3M to XM/IT, compatible play is automatically enabled. [Fix] <Jojo> Sustain loop conversion didn't work IT [Fix] <Jojo> Panning slides with both parameter nibbles set were not ignored in compatible mode. -Other modules +XM + [Fix] <Jojo> When using compatibility export, the number of samples per instrument is now limited to 16. + +MOD + [Fix] <Jojo> "+++" separator patterns were allowed in MOD files, which made them break in other trackers / players (tx 404notfound) + + +Other formats [Imp] <Jojo> DMF Loader was rewritten completely and is a whole lot more accurate now. [Fix] <Jojo> J2B Loader: Empty sample slots are now treated correct in new J2B (AM) files. + [Fix] <Jojo> DBM Loader: Global volume was scaled wrong. + [Fix] <Jojo> 8SVX Loader: If no sample could be found in the file, the loader does not claim to have successfully loaded a sample anymore. Misc [New] <Jojo> OpenMPT can now automatically check for updates (daily / weekly / monthly) + [Fix] <Jojo> When using "Convert instruments to samples" in the Song Cleanup dialog, "Remove samples associated with an instrument" actually destroyed all samples. [Reg] <Jojo> Removed hidden INI flag to suppress warnings when encountering keymaps with unknown items. This option was introduced when faulty keymaps threw multiple message boxes, but now it's just one and it shouldn't be ignored... v1.19.01.00 (April 2011, revision 836) @@ -166,7 +178,7 @@ [Fix] <Jojo> Pattern breaks >= C40 are now ignored. [Fix] <Jojo> Global volume commands > V40 are now ignored. -Other modules +Other formats [Imp] <Jojo> Garbage characters in sample / instrument / song names should be gone now.. This should f.e. avoid sample names like " ntitled" turning up in modules after deleting sample names. [Imp] <Jojo> Improved handling of the note cut effect in PTM (Polytracker) files a bit. [Mod] <Jojo> Improved portamento import precision for DBM and ULT loaders (patch from Schism Tracker) @@ -277,7 +289,7 @@ [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 +Other formats [Imp] <Jojo> Song messages are now loaded with more accuracy for some formats. [Imp] <Jojo> J2B Loader: 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. @@ -447,7 +459,7 @@ [New] <Jojo> MPTM command S7D explicitly 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. -Other modules +Other formats [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) Modified: trunk/OpenMPT/soundlib/Sampleio.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sampleio.cpp 2011-04-29 21:32:29 UTC (rev 860) +++ trunk/OpenMPT/soundlib/Sampleio.cpp 2011-05-02 17:40:15 UTC (rev 861) @@ -2138,14 +2138,15 @@ DWORD dwChunkId = *((LPDWORD)(lpMemFile+dwMemPos)); DWORD dwChunkLen = BigEndian(*((LPDWORD)(lpMemFile+dwMemPos+4))); LPBYTE pChunkData = (LPBYTE)(lpMemFile+dwMemPos+8); - if (dwChunkLen > dwFileLength - dwMemPos) break; + // Hack for broken files: Trim claimed length if it's too long + dwChunkLen = min(dwChunkLen, dwFileLength - dwMemPos); + //if (dwChunkLen > dwFileLength - dwMemPos) break; switch(dwChunkId) { case IFFID_NAME: { - UINT len = dwChunkLen; - if (len > 31) len = 31; - memset(m_szNames[nSample], 0, 32); + const UINT len = min(dwChunkLen, MAX_SAMPLENAME - 1); + MemsetZero(m_szNames[nSample]); memcpy(m_szNames[nSample], pChunkData, len); } break; @@ -2165,6 +2166,6 @@ } dwMemPos += dwChunkLen + 8; } - return true; + return (pSmp->pSample != nullptr); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-05-02 21:13:41
|
Revision: 862 http://modplug.svn.sourceforge.net/modplug/?rev=862&view=rev Author: saga-games Date: 2011-05-02 21:13:34 +0000 (Mon, 02 May 2011) Log Message: ----------- [Fix] Pattern Editor: Dropping a channel header on the plugin buttons below the channels also moved it. [Imp] IT / S3M Loaders: Clearing the MIDI macros only clears the Zxx part now. Modified Paths: -------------- trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_s3m.cpp Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-05-02 17:40:15 UTC (rev 861) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-05-02 21:13:34 UTC (rev 862) @@ -1184,7 +1184,7 @@ pModDoc->MuteChannel(nItemNo, !pModDoc->IsChannelMuted(nItemNo)); pModDoc->UpdateAllViews(this, HINT_MODCHANNELS | ((nItemNo / CHANNELS_IN_TAB) << HINT_SHIFT_CHNTAB)); } - } else if(nTargetNo < pModDoc->GetNumChannels()) + } else if(nTargetNo < pModDoc->GetNumChannels() && (m_nDropItem & DRAGITEM_MASK) == DRAGITEM_CHNHEADER) { // Dragged to other channel header => move or copy channel @@ -5230,7 +5230,7 @@ bool CViewPattern::BuildChannelControlCtxMenu(HMENU hMenu) -//-------------------------------------------------------------------- +//-------------------------------------------------------- { AppendMenu(hMenu, MF_SEPARATOR, 0, ""); Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2011-05-02 17:40:15 UTC (rev 861) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2011-05-02 21:13:34 UTC (rev 862) @@ -803,7 +803,8 @@ // Ignore MIDI data. Fixes some files like denonde.it that were made with old versions of Impulse Tracker (which didn't support Zxx filters) and have Zxx effects in the patterns. if (pifh->cwtv < 0x0214) { - MemsetZero(m_MidiCfg); + MemsetZero(m_MidiCfg.szMidiSFXExt); + MemsetZero(m_MidiCfg.szMidiZXXExt); m_dwSongFlags |= SONG_EMBEDMIDICFG; } Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp 2011-05-02 17:40:15 UTC (rev 861) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2011-05-02 21:13:34 UTC (rev 862) @@ -262,8 +262,11 @@ bKeepMidiMacros = true; // simply load Zxx commands } - if(!bKeepMidiMacros) // Remove macros so they don't interfere with other tunes - memset(&m_MidiCfg, 0, sizeof(m_MidiCfg)); + if(!bKeepMidiMacros) // Remove macros so they don't interfere with tunes made in trackers that don't support Zxx + { + MemsetZero(m_MidiCfg.szMidiSFXExt); + MemsetZero(m_MidiCfg.szMidiZXXExt); + } dwMemPos = 0x60; m_nType = MOD_TYPE_S3M; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-05-08 19:43:33
|
Revision: 866 http://modplug.svn.sourceforge.net/modplug/?rev=866&view=rev Author: saga-games Date: 2011-05-08 19:43:27 +0000 (Sun, 08 May 2011) Log Message: ----------- Added helpful documents to repo Added Paths: ----------- trunk/OpenMPT/README trunk/OpenMPT/TODO Added: trunk/OpenMPT/README =================================================================== --- trunk/OpenMPT/README (rev 0) +++ trunk/OpenMPT/README 2011-05-08 19:43:27 UTC (rev 866) @@ -0,0 +1,42 @@ +How to compile the code: + +- Visual Studio 2003/2005/2008/2010 is required. Express versions won't work as + they don't include MFC. +- The VST 2.4 and ASIO SDKs are needed for compiling with VST and ASIO support. + If you don't want this, uncomment #define NO_VST and #define NO_ASIO in the + file StdAfx.h. If you need further help with the VST and ASIO SDKs, get in + touch with the main developers. +- You need the DirectX SDK to enable DirectSound output. If you don't want this, + uncomment #define NO_DSOUND in the file StdAfx.h. + + + +Coding conventions (see below for an example): + +* Functions / methods are "underlined". +* Place curly braces at the beginning of the line, not at the end +* Generally make use of the custom index types like SAMPLEINDEX or ORDERINDEX + when referring to samples, orders, etc. +* When changing playback behaviour, make sure that you use the function +* CSoundFile::IsCompatibleMode() so that modules made with previous versions of + MPT still sound correct (if the change is extremely small, this might be + unnecessary) +* When checking the module type, use something like + if(GetType() & MOD_TYPE_XXX) + instead of + if(GetType() == MOD_TYPE_XXX) + as it could be theoretically possible that two mod types are set (currently + this doesn't happen, but in the future this might actually be used as a code + feature :) + +Code example: + +void foo::bar(int foobar) +//----------------------- +{ + while(true) + { + // some code + } +} + Added: trunk/OpenMPT/TODO =================================================================== --- trunk/OpenMPT/TODO (rev 0) +++ trunk/OpenMPT/TODO 2011-05-08 19:43:27 UTC (rev 866) @@ -0,0 +1,17 @@ +Of course there is still something that can be improved in OpenMPT, but there +are some things which definitely should be done at some point. Those include: + +* Getting rid of the buggy MFC code. Instead use something like Qt. +* While we're at it, make OpenMPT cross-platform. :) +* Developement of a proper MPTM format. Currently, it's just based on the + Impulse Tracker format and new features are hacked on at the end of the file. + Not very nice! +* Better VST support. Currently, many great VST 2.4 features like busses are not + supported. + + +Some things that could also be implemented: + +* Resizable channels with multiple effect columns. This might not be trivial at + all, especially when dealing with effects which could interfer with each other + (f.e. porta up in one column, porta down in another). \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-05-09 14:28:46
|
Revision: 869 http://modplug.svn.sourceforge.net/modplug/?rev=869&view=rev Author: saga-games Date: 2011-05-09 14:28:38 +0000 (Mon, 09 May 2011) Log Message: ----------- [Ref] Lots of oneliner refactoring that ought to be commited at some point. [Mod] Updated docs. Modified Paths: -------------- trunk/OpenMPT/TODO trunk/OpenMPT/mptrack/Mod2wave.cpp trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/SampleGenerator.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/mod2midi.cpp trunk/OpenMPT/mptrack/tagging.cpp trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/soundlib/Load_mod.cpp trunk/OpenMPT/soundlib/Load_psm.cpp trunk/OpenMPT/soundlib/midi.h trunk/OpenMPT/soundlib/patternContainer.cpp Modified: trunk/OpenMPT/TODO =================================================================== --- trunk/OpenMPT/TODO 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/TODO 2011-05-09 14:28:38 UTC (rev 869) @@ -6,7 +6,7 @@ * Developement of a proper MPTM format. Currently, it's just based on the Impulse Tracker format and new features are hacked on at the end of the file. Not very nice! -* Better VST support. Currently, many great VST 2.4 features like busses are not +* Better VST support. Currently, many great VST 2.4 features like buses are not supported. Modified: trunk/OpenMPT/mptrack/Mod2wave.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mod2wave.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/Mod2wave.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -700,6 +700,7 @@ // No pattern cue points yet m_pSndFile->m_PatternCuePoints.clear(); + m_pSndFile->m_PatternCuePoints.reserve(m_pSndFile->Order.GetLength()); // Process the conversion UINT nBytesPerSample = (CSoundFile::gnBitsPerSample * CSoundFile::gnChannels) / 8; Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -845,26 +845,29 @@ } UINT CModDoc::PlayNote(UINT note, UINT nins, UINT nsmp, BOOL bpause, LONG nVol, LONG loopstart, LONG loopend, int nCurrentChn, const uint32 nStartPos) //rewbs.vstiLive: added current chan param -//----------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------------------------------------- { CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); UINT nChn = m_SndFile.m_nChannels; if ((!pMainFrm) || (!note)) return FALSE; if (nVol > 256) nVol = 256; - if (note <= NOTE_MAX) + if (NOTE_IS_VALID(note)) { BEGIN_CRITICAL(); //kill notes if required. - if ( (bpause) || (m_SndFile.IsPaused()) || pMainFrm->GetModPlaying() != this) { + if ( (bpause) || (m_SndFile.IsPaused()) || pMainFrm->GetModPlaying() != this) + { //OnPlayerPause(); // pause song - pausing VSTis is too slow pMainFrm->SetLastMixActiveTime(); // mark activity // All notes off - for (UINT i=0; i<MAX_CHANNELS; i++) { - if ((i < m_SndFile.m_nChannels) || (m_SndFile.Chn[i].nMasterChn)) { + for (UINT i=0; i<MAX_CHANNELS; i++) + { + if ((i < m_SndFile.m_nChannels) || (m_SndFile.Chn[i].nMasterChn)) + { m_SndFile.Chn[i].dwFlags |= CHN_KEYOFF | CHN_NOTEFADE; m_SndFile.Chn[i].nFadeOutVol = 0; } @@ -890,12 +893,13 @@ MODCHANNEL *pChn = &m_SndFile.Chn[nChn]; //stop channel, just in case. - if (pChn->nLength) { + if (pChn->nLength) + { pChn->nPos = pChn->nPosLo = pChn->nLength = 0; } - //reset channel properties; in theory the chan is completely unused anyway. - pChn->dwFlags &= 0xFF; + // reset channel properties; in theory the chan is completely unused anyway. + pChn->dwFlags &= CHN_SAMPLEFLAGS; pChn->dwFlags &= ~(CHN_MUTE); pChn->nGlobalVol = 64; pChn->nInsVol = 64; @@ -905,14 +909,16 @@ pChn->nCutOff = 0x7F; pChn->nResonance = 0; pChn->nVolume = 256; - pChn->nMasterChn = 0; //remove NNA association + pChn->nMasterChn = 0; // remove NNA association pChn->nNewNote = static_cast<BYTE>(note); - if (nins) { //Set instrument + if (nins) // Set instrument + { m_SndFile.resetEnvelopes(pChn); m_SndFile.InstrumentChange(pChn, nins); } - else if ((nsmp) && (nsmp < MAX_SAMPLES)) { //Or set sample + else if ((nsmp) && (nsmp < MAX_SAMPLES)) // Or set sample + { MODSAMPLE *pSmp = &m_SndFile.Samples[nsmp]; pChn->pCurrentSample = pSmp->pSample; pChn->pModInstrument = nullptr; @@ -946,9 +952,11 @@ } // handle extra-loud flag - if ((!(CMainFrame::m_dwPatternSetup & PATTERN_NOEXTRALOUD)) && (nsmp)) { + if ((!(CMainFrame::m_dwPatternSetup & PATTERN_NOEXTRALOUD)) && (nsmp)) + { pChn->dwFlags |= CHN_EXTRALOUD; - } else { + } else + { pChn->dwFlags &= ~CHN_EXTRALOUD; } Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -356,7 +356,7 @@ if (pPlug->pPluginData) { - delete pPlug->pPluginData; + delete[] pPlug->pPluginData; pPlug->pPluginData = NULL; } if (pPlug->pMixPlugin) @@ -369,7 +369,7 @@ delete pPlug->pMixState; } - memset(&(pPlug->Info), 0, sizeof(SNDMIXPLUGININFO)); + MemsetZero(pPlug->Info); Log("Zeroing range (%d) %X - %X\n", nPlug, &(pPlug->Info), &(pPlug->Info)+sizeof(SNDMIXPLUGININFO)); pPlug->nPluginDataSize=0; pPlug->fDryRatio=0; Modified: trunk/OpenMPT/mptrack/SampleGenerator.cpp =================================================================== --- trunk/OpenMPT/mptrack/SampleGenerator.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/SampleGenerator.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -57,7 +57,7 @@ sample_clipping = dlg.GetClipping(); expression = dlg.GetExpression(); isDone = CanRenderSample(); - if(isDone) isDone = TestExpression(); // show dialog again if the formular can't be parsed. + if(isDone) isDone = TestExpression(); // show dialog again if the formula can't be parsed. result = true; } else { Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -2567,20 +2567,20 @@ nRows = pSndFile->Patterns[m_nPattern].GetNumRows(); pOldPattern = pSndFile->Patterns[m_nPattern]; if ((nChannels < 1) || (nRows < 1) || (!pOldPattern)) return; - dx = (int)((m_dwDragPos & 0xFFF8) >> 3) - (int)((m_dwStartSel & 0xFFF8) >> 3); + dx = (int)GetChanFromCursor(m_dwDragPos) - (int)GetChanFromCursor(m_dwStartSel); dy = (int)GetRowFromCursor(m_dwDragPos) - (int)GetRowFromCursor(m_dwStartSel); if ((!dx) && (!dy)) return; pModDoc->GetPatternUndo()->PrepareUndo(m_nPattern, 0,0, nChannels, nRows); pNewPattern = CPattern::AllocatePattern(nRows, nChannels); if (!pNewPattern) return; - x1 = (m_dwBeginSel & 0xFFF8) >> 3; - y1 = (m_dwBeginSel) >> 16; - x2 = (m_dwEndSel & 0xFFF8) >> 3; - y2 = (m_dwEndSel) >> 16; - c1 = (m_dwBeginSel&7); - c2 = (m_dwEndSel&7); - if (c1 > 3) c1 = 3; - if (c2 > 3) c2 = 3; + x1 = GetChanFromCursor(m_dwBeginSel); + y1 = GetRowFromCursor(m_dwBeginSel); + x2 = GetChanFromCursor(m_dwEndSel); + y2 = GetRowFromCursor(m_dwEndSel); + c1 = GetColTypeFromCursor(m_dwBeginSel); + c2 = GetColTypeFromCursor(m_dwEndSel); + if (c1 > EFFECT_COLUMN) c1 = EFFECT_COLUMN; + if (c2 > EFFECT_COLUMN) c2 = EFFECT_COLUMN; xc1 = x1*4+c1; xc2 = x2*4+c2; xmc1 = xc1+dx*4; @@ -2645,7 +2645,7 @@ if (c2 >= 3) c2 = 4; // Fix: Horizontal scrollbar pos screwed when selecting with mouse SetCursorPosition( y1, (x1<<3)|c1 ); - SetCurSel((y1<<16)|(x1<<3)|c1, (y2<<16)|(x2<<3)|c2); + SetCurSel(CreateCursor(y1, x1, c1), CreateCursor(y2, x2, c2)); InvalidatePattern(); CPattern::FreePattern(pOldPattern); pModDoc->SetModified(); Modified: trunk/OpenMPT/mptrack/mod2midi.cpp =================================================================== --- trunk/OpenMPT/mptrack/mod2midi.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/mod2midi.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -134,7 +134,7 @@ strcpy(m_szFileName, pszPathName); _splitpath(pszPathName, NULL, NULL, NULL, fext); if (!_stricmp(fext, ".rmi")) m_bRmi = TRUE; - memset(m_InstrMap, 0, sizeof(m_InstrMap)); + MemsetZero(m_InstrMap); for (UINT nIns=1; nIns<=m_pSndFile->m_nInstruments; nIns++) { MODINSTRUMENT *pIns = m_pSndFile->Instruments[nIns]; Modified: trunk/OpenMPT/mptrack/tagging.cpp =================================================================== --- trunk/OpenMPT/mptrack/tagging.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/mptrack/tagging.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -125,7 +125,7 @@ WAVEDATAHEADER chunk; CHAR s[256]; DWORD info_ofs, end_ofs; - DWORD zero = 0; + const DWORD zero = 0; info_ofs = ftell(f); if (info_ofs & 1) Modified: trunk/OpenMPT/packageTemplate/History.txt =================================================================== --- trunk/OpenMPT/packageTemplate/History.txt 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/packageTemplate/History.txt 2011-05-09 14:28:38 UTC (rev 869) @@ -10,44 +10,55 @@ (tx XYZ): thanks to XYZ for telling us about the bug / requesting the feature -v1.19.02.00 (***** 2011, revision 861) --------------------------------------- -Pattern tab::Note properties - [New] <Jojo> Channels can now be moved by dragging their channel header. Holding Shift while doing so duplicates the channel +v1.19.02.00 (May 2011, revision 869) +------------------------------------ +Pattern tab + [New] <Jojo> Channels can now be moved by dragging their channel header. Holding Shift while doing so duplicates the channel. [Imp] <Jojo> Moving channels through the channel manager creates an undo point now. - [Fix] <Jojo> Axx is not limited to value 7F anymore in IT / S3M format. [Fix] <Jojo> Order list info text now truncates list length after the first "---" pattern for MOD files in hex display mode as well. +Pattern tab::Note properties + [Fix] <Jojo> Axx is not limited to value 7F anymore in IT / S3M format. + VST [New] <Jojo> New menu entry in the plugin editor: Create instrument from plugin [Fix] <Jojo> Fixed note handling in VST editor of plugins that actually don't support MIDI input (http://bugs.openmpt.org/view.php?id=102) Mod Conversion [Imp] <Jojo> Improved conversion of Sxx (IT / S3M) and PC Notes. - [Mod] <Jojo> When converting from MOD/S3M to XM/IT, compatible play is automatically enabled. + [Mod] <Jojo> When converting from MOD / S3M to XM / IT, compatible play is automatically enabled. [Fix] <Jojo> Sustain loop conversion didn't work +Playback + [Fix] <Jojo> The first triggered note in the pattern / sample / instrument editor is not cut off anymore (tx C-jeff, http://bugs.openmpt.org/view.php?id=123) + IT + [Imp] <Jojo> When clearing MIDI macros during loading, only the Zxx macros are cleared, but not the global (currently unused) configuration. [Fix] <Jojo> Panning slides with both parameter nibbles set were not ignored in compatible mode. XM [Fix] <Jojo> When using compatibility export, the number of samples per instrument is now limited to 16. MOD - [Fix] <Jojo> "+++" separator patterns were allowed in MOD files, which made them break in other trackers / players (tx 404notfound) + [Imp] <Jojo> Instead of cutting the order list after the first --- pattern, such order items are simply removed from the saved order list. (http://bugs.openmpt.org/view.php?id=118) + [Fix] <Jojo> "+++" separator patterns were allowed in MOD files, which made them break in other trackers / players. (http://bugs.openmpt.org/view.php?id=118) +S3M + [Imp] <Jojo> When clearing MIDI macros during loading, only the Zxx macros are cleared, but not the global (currently unused) configuration. Other formats [Imp] <Jojo> DMF Loader was rewritten completely and is a whole lot more accurate now. - [Fix] <Jojo> J2B Loader: Empty sample slots are now treated correct in new J2B (AM) files. + [Fix] <Jojo> J2B Loader: Empty sample slots are now treated correct in new (RIFF AM) J2B files. [Fix] <Jojo> DBM Loader: Global volume was scaled wrong. - [Fix] <Jojo> 8SVX Loader: If no sample could be found in the file, the loader does not claim to have successfully loaded a sample anymore. + [Fix] <Jojo> 8SVX Loader: If no sample could be found in the file, the loader does not claim to have successfully loaded a sample anymore. (http://bugs.openmpt.org/view.php?id=117) Misc [New] <Jojo> OpenMPT can now automatically check for updates (daily / weekly / monthly) + [Mod] <Jojo> "Embed MIDI macros" is now only enabled during song creation if the user's default MIDI macro setup differs from standard configuration. [Fix] <Jojo> When using "Convert instruments to samples" in the Song Cleanup dialog, "Remove samples associated with an instrument" actually destroyed all samples. [Reg] <Jojo> Removed hidden INI flag to suppress warnings when encountering keymaps with unknown items. This option was introduced when faulty keymaps threw multiple message boxes, but now it's just one and it shouldn't be ignored... + v1.19.01.00 (April 2011, revision 836) -------------------------------------- Pattern tab @@ -1046,13 +1057,13 @@ [Mod] <Jojo> Sustain loop will now be enabled when setting it to sample selection. (rev. 231) [Mod] <Jojo> Sample editing: If possible, use loop points as trim limits if there's no selection chosen. (rev. 230) [Mod] <re> Time stretching is now implemented with SoundTouch library. (rev. 228) - [Mod] <re> Disabled pitchshifting/time stretching of 8-bit samples(didn't seem to work). (rev. 228) + [Mod] <re> Disabled pitchshifting/time stretching of 8-bit samples (didn't seem to work). (rev. 228) Instrument tab [Fix] <Jojo> Envelope view: Middle line will now be drawn in panning and pitch/filter envelopes even if row guidelines are enabled. (rev. 254) [Mod] <Jojo> Instrument tab: Sample map can now map "No sample". (rev. 236) - [Mod] <re> Changed default instrument plug volume command handling from Dry/Wet to none. Also added ini-setting with which one can set the default value used for new instruments. Ini setting is "DefaultPlugVolumeHandling" in [Misc], possible values are 0,1,2. (rev. 238) + [Mod] <re> Changed default instrument plug volume command handling from Dry/Wet to none. Also added INI setting with which one can set the default value used for new instruments. INI setting is "DefaultPlugVolumeHandling" in [Misc], possible values are 0,1,2. (rev. 238) MPTM [Fix] <re> Pattern cleanup: In some cases sequence wasn't cleaned properly for mptm. (rev. 239) @@ -1081,14 +1092,13 @@ [Fix] <Jojo & re> Fixes to MOD saving: it should now be possible to create ProTracker compatible MOD files with compatibility export. (rev. 256) Package template - [Mod] <Jojo> PackageTemplate: Update to DE_jojo.mkb keymap + [Mod] <Jojo> Updated DE_jojo.mkb keymap Misc [Fix] <from libmodplug> Fix to faulty portamento handling on loading AMF. [Fix] <various> Lots of smaller bug fixes. - v1.17.02.52 (14 Apr 2008, revision 210) --------------------------------------- [Fix] <re> Shouldn't need winhttp anymore (at least now that updatecheck is disabled). Dependency caused problems in Win98. Modified: trunk/OpenMPT/soundlib/Load_mod.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mod.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/soundlib/Load_mod.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -489,7 +489,7 @@ } } } - // Arbitrary thershold for going into PT1x mode: 16 "sample swaps" in one pattern. + // Arbitrary threshold for going into PT1x mode: 16 "sample swaps" in one pattern. if(instrWithoutNoteCount > 16) { m_dwSongFlags |= SONG_PT1XMODE; Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -160,10 +160,10 @@ m_nVSTiVolume = m_nSamplePreAmp = 48; // not supported in this format, so use a good default value // pattern offset and identifier - PATTERNINDEX numPatterns = 0; // used for setting up the orderlist - final pattern count - vector<uint32> patternOffsets; // pattern offsets (sorted as they occour in the file) - vector<uint32> patternIDs; // pattern IDs (sorted as they occour in the file) - vector<uint32> orderOffsets; // combine the upper two vectors to get the offsets for each order item + PATTERNINDEX numPatterns = 0; // used for setting up the orderlist - final pattern count + vector<uint32> patternOffsets; // pattern offsets (sorted as they occour in the file) + vector<uint32> patternIDs; // pattern IDs (sorted as they occour in the file) + vector<uint32> orderOffsets; // combine the upper two vectors to get the offsets for each order item patternOffsets.clear(); patternIDs.clear(); orderOffsets.clear(); @@ -253,7 +253,7 @@ if(subChunkSize < 9) return false; // First two bytes = Number of chunks that follow //uint16 nTotalChunks = LittleEndian(*(uint16 *)(lpStream + dwChunkPos)); - + // Now, the interesting part begins! DWORD dwSettingsOffset = dwChunkPos + 2; uint16 nChunkCount = 0, nFirstOrderChunk = uint16_max; Modified: trunk/OpenMPT/soundlib/midi.h =================================================================== --- trunk/OpenMPT/soundlib/midi.h 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/soundlib/midi.h 2011-05-09 14:28:38 UTC (rev 869) @@ -18,7 +18,10 @@ { MIDIEVENT_NOTEOFF = 0x8, MIDIEVENT_NOTEON = 0x9, + MIDIEVENT_POLYAFTERTOUCH = 0xA, MIDIEVENT_CONTROLLERCHANGE = 0xB, + MIDIEVENT_PROGRAMCHANGE = 0xC, + MIDIEVENT_CHANAFTERTOUCH = 0xD, MIDIEVENT_PITCHBEND = 0xE, MIDISTATUS_ACTIVESENSING = 0xFE }; Modified: trunk/OpenMPT/soundlib/patternContainer.cpp =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.cpp 2011-05-08 20:31:56 UTC (rev 868) +++ trunk/OpenMPT/soundlib/patternContainer.cpp 2011-05-09 14:28:38 UTC (rev 869) @@ -87,7 +87,7 @@ if(!IsValidPat(nPat)) return false; - MODCOMMAND *m = m_Patterns[nPat].m_ModCommands; + const MODCOMMAND *m = m_Patterns[nPat].m_ModCommands; for(size_t i = m_Patterns[nPat].GetNumChannels() * m_Patterns[nPat].GetNumRows(); i > 0; i--, m++) { if(!m->IsEmpty(true)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-05-10 14:27:16
|
Revision: 870 http://modplug.svn.sourceforge.net/modplug/?rev=870&view=rev Author: saga-games Date: 2011-05-10 14:27:05 +0000 (Tue, 10 May 2011) Log Message: ----------- [Mod] Changed some terms as suggested in http://bugs.openmpt.org/view.php?id=100 [Mod] Removed inline modifier from SanitizeFilename() [Mod] Updated release notes [Mod] OpenMPT: Version is now 1.19.01.07 Modified Paths: -------------- trunk/OpenMPT/mptrack/CommandSet.cpp trunk/OpenMPT/mptrack/InputHandler.cpp trunk/OpenMPT/mptrack/View_pat.cpp trunk/OpenMPT/mptrack/misc_util.h trunk/OpenMPT/mptrack/mptrack.rc trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/packageTemplate/OMPT_1.19_ReleaseNotes.html Modified: trunk/OpenMPT/mptrack/CommandSet.cpp =================================================================== --- trunk/OpenMPT/mptrack/CommandSet.cpp 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/mptrack/CommandSet.cpp 2011-05-10 14:27:05 UTC (rev 870) @@ -564,7 +564,7 @@ DefineKeyCommand(kcOrderlistPatPlus, 1817, kcVisible, kcNoDummy, _T("Increase pattern index ")); DefineKeyCommand(kcOrderlistPatMinus, 1818, kcVisible, kcNoDummy, _T("Decrease pattern index")); DefineKeyCommand(kcShowSplitKeyboardSettings, 1819, kcVisible, kcNoDummy, _T("Split Keyboard Settings dialog")); - DefineKeyCommand(kcEditPushForwardPaste, 1820, kcVisible, kcNoDummy, _T("Push Forward Paste")); + DefineKeyCommand(kcEditPushForwardPaste, 1820, kcVisible, kcNoDummy, _T("Push Forward Paste (Insert)")); DefineKeyCommand(kcInstrumentEnvelopePointMoveLeft, 1821, kcVisible, kcNoDummy, _T("Move envelope point left")); DefineKeyCommand(kcInstrumentEnvelopePointMoveRight, 1822, kcVisible, kcNoDummy, _T("Move envelope point right")); DefineKeyCommand(kcInstrumentEnvelopePointMoveUp, 1823, kcVisible, kcNoDummy, _T("Move envelope point up")); @@ -597,7 +597,7 @@ DefineKeyCommand(kcInsNoteMapEditSampleMap, 1850, kcVisible, kcNoDummy, _T("Edit sample map")); DefineKeyCommand(kcInstrumentCtrlDuplicate, 1851, kcVisible, kcNoDummy, _T("Duplicate instrument")); DefineKeyCommand(kcPanic, 1852, kcVisible, kcNoDummy, _T("Panic")); - DefineKeyCommand(kcOrderlistPatIgnore, 1853, kcVisible, kcNoDummy, _T("Ignore (+++) Index")); + DefineKeyCommand(kcOrderlistPatIgnore, 1853, kcVisible, kcNoDummy, _T("Separator (+++) Index")); DefineKeyCommand(kcOrderlistPatInvalid, 1854, kcVisible, kcNoDummy, _T("Invalid (---) Index")); DefineKeyCommand(kcViewEditHistory, 1855, kcVisible, kcNoDummy, _T("View Edit History")); DefineKeyCommand(kcSampleQuickFade, 1856, kcVisible, kcNoDummy, _T("Quick fade")); Modified: trunk/OpenMPT/mptrack/InputHandler.cpp =================================================================== --- trunk/OpenMPT/mptrack/InputHandler.cpp 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/mptrack/InputHandler.cpp 2011-05-10 14:27:05 UTC (rev 870) @@ -448,7 +448,7 @@ case ID_EDIT_PASTE_SPECIAL: s="&Mix Paste\t"; c=kcEditMixPaste; break; case ID_EDIT_MIXPASTE_ITSTYLE: s="&Mix Paste (IT Style)\t"; c=kcEditMixPasteITStyle; break; case ID_EDIT_PASTEFLOOD: s="Paste Fl&ood\t"; c=kcEditPasteFlood; break; - case ID_EDIT_PUSHFORWARDPASTE: s="&Push Forward Paste\t"; c=kcEditPushForwardPaste; break; + case ID_EDIT_PUSHFORWARDPASTE: s="&Push Forward Paste (Insert)\t"; c=kcEditPushForwardPaste; break; case ID_VIEW_GLOBALS: s="&General\t"; c=kcViewGeneral; break; case ID_VIEW_SAMPLES: s="&Samples\t"; c=kcViewSamples; break; Modified: trunk/OpenMPT/mptrack/View_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/mptrack/View_pat.cpp 2011-05-10 14:27:05 UTC (rev 870) @@ -5159,7 +5159,7 @@ AppendMenu(pasteSpecialMenu, MF_STRING, ID_EDIT_MIXPASTE, "Mix Paste\t" + ih->GetKeyTextFromCommand(kcEditMixPaste)); AppendMenu(pasteSpecialMenu, MF_STRING, ID_EDIT_MIXPASTE_ITSTYLE, "Mix Paste (IT Style)\t" + ih->GetKeyTextFromCommand(kcEditMixPasteITStyle)); AppendMenu(pasteSpecialMenu, MF_STRING, ID_EDIT_PASTEFLOOD, "Paste Flood\t" + ih->GetKeyTextFromCommand(kcEditPasteFlood)); - AppendMenu(pasteSpecialMenu, MF_STRING, ID_EDIT_PUSHFORWARDPASTE, "Push Forward Paste\t" + ih->GetKeyTextFromCommand(kcEditPushForwardPaste)); + AppendMenu(pasteSpecialMenu, MF_STRING, ID_EDIT_PUSHFORWARDPASTE, "Push Forward Paste (Insert)\t" + ih->GetKeyTextFromCommand(kcEditPushForwardPaste)); DWORD greyed = pModDoc->GetPatternUndo()->CanUndo()?FALSE:MF_GRAYED; if (!greyed || !(CMainFrame::m_dwPatternSetup & PATTERN_OLDCTXMENUSTYLE)) Modified: trunk/OpenMPT/mptrack/misc_util.h =================================================================== --- trunk/OpenMPT/mptrack/misc_util.h 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/mptrack/misc_util.h 2011-05-10 14:27:05 UTC (rev 870) @@ -124,8 +124,8 @@ // Sanitize a filename (remove special chars) template <size_t size> -inline void SanitizeFilename(char (&buffer)[size]) -//------------------------------------------------ +void SanitizeFilename(char (&buffer)[size]) +//----------------------------------------- { STATIC_ASSERT(size > 0); for(size_t i = 0; i < size; i++) Modified: trunk/OpenMPT/mptrack/mptrack.rc =================================================================== --- trunk/OpenMPT/mptrack/mptrack.rc 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/mptrack/mptrack.rc 2011-05-10 14:27:05 UTC (rev 870) @@ -2014,7 +2014,7 @@ MENUITEM "&Mix Paste\tCtrl+M", ID_EDIT_PASTE_SPECIAL MENUITEM "Mix Paste (IT Style)", ID_EDIT_MIXPASTE_ITSTYLE MENUITEM "Paste &Flood", ID_EDIT_PASTEFLOOD - MENUITEM "&Push Forward Paste", ID_EDIT_PUSHFORWARDPASTE + MENUITEM "&Push Forward Paste (Insert)", ID_EDIT_PUSHFORWARDPASTE END MENUITEM "Select &All\tCtrl+5", ID_EDIT_SELECT_ALL MENUITEM SEPARATOR Modified: trunk/OpenMPT/mptrack/version.h =================================================================== --- trunk/OpenMPT/mptrack/version.h 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/mptrack/version.h 2011-05-10 14:27:05 UTC (rev 870) @@ -15,7 +15,7 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 19 #define VER_MINOR 01 -#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/packageTemplate/OMPT_1.19_ReleaseNotes.html =================================================================== --- trunk/OpenMPT/packageTemplate/OMPT_1.19_ReleaseNotes.html 2011-05-09 14:28:38 UTC (rev 869) +++ trunk/OpenMPT/packageTemplate/OMPT_1.19_ReleaseNotes.html 2011-05-10 14:27:05 UTC (rev 870) @@ -88,6 +88,7 @@ <a href="ReleaseNotesImages/1.19/edithistory.png"><img src="ReleaseNotesImages/1.19/edithistory.png" width="240" height="163" alt="Edit history dialog" title="Edit history dialog (click to view big screenshot)" /></a> </div> <ul> + <li>OpenMPT comes with an automated <strong>update check</strong> again, which can notify you of new program versions.</li> <li>Based on an undocumented feature in Impulse Tracker, OpenMPT can now save an <strong>edit history</strong> in IT and MPTM files, which reveals when and for how long a module has been edited in the tracker.</li> <li>When exporting to WAV, <strong>cue points</strong> are now inserted at every pattern transition.</li> <li>The last remaining absolute paths in the settings files have been removed; OpenMPT is now <strong>fully portable</strong>!</li> @@ -102,6 +103,7 @@ <img src="ReleaseNotesImages/1.19/timesignature.png" width="291" height="228" alt="Per-pattern time signatures" title="Per-pattern time signatures" /> </div> <ul> + <li><strong>Channels can be moved</strong> by dragging the channel headers.</li> <li><strong>Per-pattern time signatures</strong> allow to override the global time signature. This is especially useful in modern tempo mode if you want to use several time signatures in the same song, or if you just temporarily need more detail in a pattern.</li> <li>You can now <strong>select whole rows</strong> by clicking / dragging the row index on the left side of the pattern.</li> <li>There are new shortcuts for <strong>selecting a whole beat or measure</strong>.</li> @@ -132,6 +134,7 @@ <h3>VST Plugins</h3> <ul> <li><strong>Much improved compatibility</strong> with many VST 2.4 plugins! Examples of plugins that work better in this version: Voxengo SPAN 2, Angelina, EnergyXT, MetroGnome.</li> + <li>It is even easier to <strong>create multiple mod instruments</strong> from a plugin now: Simply choose "Create instrument from plugin" from the plugin editor's "File" menu.</li> </ul> <h3>There's more...</h3> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <sag...@us...> - 2011-05-13 13:59:27
|
Revision: 871 http://modplug.svn.sourceforge.net/modplug/?rev=871&view=rev Author: saga-games Date: 2011-05-13 13:59:18 +0000 (Fri, 13 May 2011) Log Message: ----------- [Mod] Updated package template and installer code [Fix] Fixed memory leak in internet update code when download code fails (which practically shouldn't happen at all) [Mod] OpenMPT: Version is no 1.19.02.00 Modified Paths: -------------- trunk/OpenMPT/installer/install-unmo3-free-itd.iss trunk/OpenMPT/installer/install-unmo3-free.iss trunk/OpenMPT/installer/install.iss trunk/OpenMPT/installer/packageTemplate/readme.txt trunk/OpenMPT/mptrack/UpdateCheck.cpp trunk/OpenMPT/mptrack/version.h trunk/OpenMPT/packageTemplate/History.txt trunk/OpenMPT/packageTemplate/OMPT_1.19_ReleaseNotes.html trunk/OpenMPT/packageTemplate/readme.txt Removed Paths: ------------- trunk/OpenMPT/mptrack/Mptrack.opt trunk/OpenMPT/mptrack/mptrack.plg Modified: trunk/OpenMPT/installer/install-unmo3-free-itd.iss =================================================================== --- trunk/OpenMPT/installer/install-unmo3-free-itd.iss 2011-05-10 14:27:05 UTC (rev 870) +++ trunk/OpenMPT/installer/install-unmo3-free-itd.iss 2011-05-13 13:59:18 UTC (rev 871) @@ -23,7 +23,7 @@ begin if(GetSHA1OfFile(ExpandConstant('{tmp}\openmpt-unmo3.dll.tmp')) <> '393be7e0f50c62d142386a16d6855ca771025554') then begin - MsgBox('Warning: unmo3.dll has been downloaded, but its checksum is wrong! This means that either the downloaded file is corrupted or that a newer version of unmo3.dll is available. The file has thus not been installed. Please obtain unmo3.dll from http://openmpt.com/ and verify its checksum.', mbCriticalError, MB_OK) + MsgBox('Warning: unmo3.dll has been downloaded, but its checksum is wrong! This means that either the downloaded file is corrupted or that a newer version of unmo3.dll is available. The file has thus not been installed. Please obtain unmo3.dll from http://openmpt.org/ and verify its checksum.', mbCriticalError, MB_OK) end else begin FileCopy(ExpandConstant('{tmp}\openmpt-unmo3.dll.tmp'), ExpandConstant('{app}\unmo3.dll'), true); Modified: trunk/OpenMPT/installer/install-unmo3-free.iss =================================================================== --- trunk/OpenMPT/installer/install-unmo3-free.iss 2011-05-10 14:27:05 UTC (rev 870) +++ trunk/OpenMPT/installer/install-unmo3-free.iss 2011-05-13 13:59:18 UTC (rev 871) @@ -22,7 +22,7 @@ begin if(GetSHA1OfFile(ExpandConstant('{tmp}\openmpt-unmo3.dll.tmp')) <> '393be7e0f50c62d142386a16d6855ca771025554') then begin - MsgBox('Warning: unmo3.dll has been downloaded, but its checksum is wrong! This means that either the downloaded file is corrupted or that a newer version of unmo3.dll is available. The file has thus not been installed. Please obtain unmo3.dll from http://openmpt.com/ and verify its checksum.', mbCriticalError, MB_OK) + MsgBox('Warning: unmo3.dll has been downloaded, but its checksum is wrong! This means that either the downloaded file is corrupted or that a newer version of unmo3.dll is available. The file has thus not been installed. Please obtain unmo3.dll from http://openmpt.org/ and verify its checksum.', mbCriticalError, MB_OK) end else begin FileCopy(ExpandConstant('{tmp}\openmpt-unmo3.dll.tmp'), ExpandConstant('{app}\unmo3.dll'), true); Modified: trunk/OpenMPT/installer/install.iss =================================================================== --- trunk/OpenMPT/installer/install.iss 2011-05-10 14:27:05 UTC (rev 870) +++ trunk/OpenMPT/installer/install.iss 2011-05-13 13:59:18 UTC (rev 871) @@ -73,8 +73,8 @@ ; release notes Source: ..\packageTemplate\ReleaseNotesImages\general\*.*; DestDir: {app}\ReleaseNotesImages\general\; Flags: ignoreversion sortfilesbyextension -Source: ..\packageTemplate\ReleaseNotesImages\1.19\*.*; DestDir: {app}\ReleaseNotesImages\1.19\; Flags: ignoreversion sortfilesbyextension -Source: ..\packageTemplate\OMPT_1.19_ReleaseNotes.html; DestDir: {app}; Flags: ignoreversion +Source: ..\packageTemplate\ReleaseNotesImages\{#GetAppVersionShort}\*.*; DestDir: {app}\ReleaseNotesImages\{#GetAppVersionShort}\; Flags: ignoreversion sortfilesbyextension +Source: ..\packageTemplate\OMPT_{#GetAppVersionShort}_ReleaseNotes.html; DestDir: {app}; Flags: ignoreversion ; soundtouch license stuff Source: ..\packageTemplate\SoundTouch\*.*; DestDir: {app}\SoundTouch; Flags: ignoreversion sortfilesbyextension Modified: trunk/OpenMPT/installer/packageTemplate/readme.txt =================================================================== --- trunk/OpenMPT/installer/packageTemplate/readme.txt 2011-05-10 14:27:05 UTC (rev 870) +++ trunk/OpenMPT/installer/packageTemplate/readme.txt 2011-05-13 13:59:18 UTC (rev 871) @@ -34,14 +34,14 @@ Release package contents: ------------------------- -extraKeymaps(folder): Additional key bindings for the keyboard manager, - available in several flavours (including MPT classic, FastTracker and +extraKeymaps (folder): Additional key bindings for the keyboard manager, + available in several flavours (including MPT classic, Fasttracker 2 and Impulse Tracker) and country-specific layouts. -soundtouch(folder): SoundTouch readme and copying.txt -ReleaseNotesImages(folder): Images using in the release notes document. -ExampleSongs(folder): A set of module files which should give an impression of +SoundTouch (folder): SoundTouch readme and license +ReleaseNotesImages (folder): Files used in the release notes document. +ExampleSongs (folder): A set of module files which should give an impression of what can be done in OpenMPT with only a few kilobytes. -history.txt: Version history. +History.txt: Version history. mptrack.exe: Main executable. OpenMPT_SoundTouch_i16.dll: Slightly customized SoundTouch library used in time stretching feature. Deleted: trunk/OpenMPT/mptrack/Mptrack.opt =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.opt 2011-05-10 14:27:05 UTC (rev 870) +++ trunk/OpenMPT/mptrack/Mptrack.opt 2011-05-13 13:59:18 UTC (rev 871) @@ -1,31 +0,0 @@ -\xD0\xCFࡱ\xE1 |
From: <sag...@us...> - 2011-05-15 20:26:28
|
Revision: 873 http://modplug.svn.sourceforge.net/modplug/?rev=873&view=rev Author: saga-games Date: 2011-05-15 20:26:20 +0000 (Sun, 15 May 2011) Log Message: ----------- [Ref] Pattern names are now stored in CPattern. [Fix] ITP Saver: Fixed nasty bug when the internal order length was not 256. Modified Paths: -------------- trunk/OpenMPT/mptrack/CleanupSong.cpp trunk/OpenMPT/mptrack/Ctrl_pat.cpp trunk/OpenMPT/mptrack/Ctrl_seq.cpp trunk/OpenMPT/mptrack/MPTHacks.cpp trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp trunk/OpenMPT/mptrack/View_tre.cpp trunk/OpenMPT/soundlib/Load_ams.cpp trunk/OpenMPT/soundlib/Load_it.cpp trunk/OpenMPT/soundlib/Load_itp.cpp trunk/OpenMPT/soundlib/Load_med.cpp trunk/OpenMPT/soundlib/Load_mid.cpp trunk/OpenMPT/soundlib/Load_psm.cpp trunk/OpenMPT/soundlib/Load_xm.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/Sndfile.h trunk/OpenMPT/soundlib/pattern.cpp trunk/OpenMPT/soundlib/pattern.h trunk/OpenMPT/soundlib/patternContainer.cpp trunk/OpenMPT/soundlib/patternContainer.h Modified: trunk/OpenMPT/mptrack/CleanupSong.cpp =================================================================== --- trunk/OpenMPT/mptrack/CleanupSong.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/CleanupSong.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -340,6 +340,20 @@ /////////////////////////////////////////////////////////////////////// // Actual cleanup implementations +struct OrigPatSettings +{ + bool isPatUsed; // Is pattern used in sequence? + PATTERNINDEX newIndex; // map old pattern index <-> new pattern index + // This stuff is needed for copying the old pattern properties to the new pattern number + MODCOMMAND *data; // original pattern data + ROWINDEX numRows; // original pattern sizes + ROWINDEX rowsPerBeat; // original pattern highlight + ROWINDEX rowsPerMeasure; // original pattern highlight + CString name; // original pattern name +}; + +const OrigPatSettings defaultSettings = {false, 0, nullptr, 0, 0, 0, ""}; + // Remove unused patterns / rearrange patterns // If argument bRemove is true, unused patterns are removed. Else, patterns are only rearranged. bool CModCleanupDlg::RemoveUnusedPatterns(bool bRemove) @@ -350,13 +364,7 @@ const SEQUENCEINDEX maxSeqIndex = pSndFile->Order.GetNumSequences(); const PATTERNINDEX maxPatIndex = pSndFile->Patterns.Size(); - vector<bool> bPatUsed(maxPatIndex, false); // used patterns - vector<PATTERNINDEX> nPatMap(maxPatIndex, 0); // map old pattern index <-> new pattern index - // Those vectors are needed for copying the old pattern properties to the new pattern number - vector<MODCOMMAND*> pPatterns(maxPatIndex, nullptr); // original pattern data - vector<ROWINDEX> nPatRows(maxPatIndex, 0); // original pattern sizes - vector<ROWINDEX> nPatRowsPerBeat(maxPatIndex, 0); // original pattern highlight - vector<ROWINDEX> nPatRowsPerMeasure(maxPatIndex, 0); // original pattern highlight + vector<OrigPatSettings> patternSettings(maxPatIndex, defaultSettings); CHAR s[512]; bool bReordered = false; @@ -374,7 +382,7 @@ if (n < maxPatIndex) { if (n >= maxpat) maxpat = n + 1; - bPatUsed[n] = true; + patternSettings[n].isPatUsed = true; } } } @@ -386,7 +394,7 @@ while (imax > 0) { imax--; - if ((pSndFile->Patterns[imax]) && (bPatUsed[imax])) break; + if ((pSndFile->Patterns[imax]) && (patternSettings[imax].isPatUsed)) break; } nMinToRemove = imax + 1; } @@ -407,7 +415,7 @@ size_t nWaste = 0; for (UINT ichk=0; ichk < maxPatIndex; ichk++) { - if ((pSndFile->Patterns[ichk]) && (!bPatUsed[ichk])) nWaste++; + if ((pSndFile->Patterns[ichk]) && (!patternSettings[ichk].isPatUsed)) nWaste++; } if ((bRemove) && (nWaste)) @@ -419,7 +427,7 @@ } for(PATTERNINDEX i = 0; i < maxPatIndex; i++) - nPatMap[i] = PATTERNINDEX_INVALID; + patternSettings[i].newIndex = PATTERNINDEX_INVALID; SEQUENCEINDEX oldSequence = pSndFile->Order.GetCurrentSequenceIndex(); // workaround, as GetSequence doesn't allow writing to sequences ATM @@ -434,8 +442,8 @@ PATTERNINDEX n = pSndFile->Order.GetSequence(nSeq)[imap]; if (n < maxPatIndex) { - if (nPatMap[n] == PATTERNINDEX_INVALID) nPatMap[n] = nPats++; - pSndFile->Order[imap] = nPatMap[n]; + if (patternSettings[n].newIndex == PATTERNINDEX_INVALID) patternSettings[n].newIndex = nPats++; + pSndFile->Order[imap] = patternSettings[n].newIndex; } } // Add unused patterns at the end @@ -443,9 +451,9 @@ { for(PATTERNINDEX iadd = 0; iadd < maxPatIndex; iadd++) { - if((pSndFile->Patterns[iadd]) && (nPatMap[iadd] >= maxPatIndex)) + if((pSndFile->Patterns[iadd]) && (patternSettings[iadd].newIndex >= maxPatIndex)) { - nPatMap[iadd] = nPats++; + patternSettings[iadd].newIndex = nPats++; } } } @@ -460,35 +468,20 @@ // Reorder patterns & Delete unused patterns BEGIN_CRITICAL(); { - const UINT npatnames = pSndFile->m_nPatternNames; - const LPSTR lpszpatnames = pSndFile->m_lpszPatternNames; - pSndFile->m_nPatternNames = 0; - pSndFile->m_lpszPatternNames = nullptr; for (PATTERNINDEX i = 0; i < maxPatIndex; i++) { - PATTERNINDEX k = nPatMap[i]; + PATTERNINDEX k = patternSettings[i].newIndex; if (k < maxPatIndex) { if (i != k) bReordered = true; - // Remap pattern names - if (i < npatnames) - { - UINT noldpatnames = pSndFile->m_nPatternNames; - LPSTR lpszoldpatnames = pSndFile->m_lpszPatternNames; - pSndFile->m_nPatternNames = npatnames; - pSndFile->m_lpszPatternNames = lpszpatnames; - pSndFile->GetPatternName(i, s); - pSndFile->m_nPatternNames = noldpatnames; - pSndFile->m_lpszPatternNames = lpszoldpatnames; - if (s[0]) pSndFile->SetPatternName(k, s); - } - nPatRows[k] = pSndFile->Patterns[i].GetNumRows(); - pPatterns[k] = pSndFile->Patterns[i]; + patternSettings[k].numRows = pSndFile->Patterns[i].GetNumRows(); + patternSettings[k].data = pSndFile->Patterns[i]; if(pSndFile->Patterns[i].GetOverrideSignature()) { - nPatRowsPerBeat[k] = pSndFile->Patterns[i].GetRowsPerBeat(); - nPatRowsPerMeasure[k] = pSndFile->Patterns[i].GetRowsPerMeasure(); + patternSettings[k].rowsPerBeat = pSndFile->Patterns[i].GetRowsPerBeat(); + patternSettings[k].rowsPerMeasure = pSndFile->Patterns[i].GetRowsPerMeasure(); } + patternSettings[k].name = pSndFile->Patterns[i].GetName(); } else if (pSndFile->Patterns[i]) { @@ -498,11 +491,10 @@ } for (PATTERNINDEX nPat = 0; nPat < maxPatIndex; nPat++) { - pSndFile->Patterns[nPat].SetData(pPatterns[nPat], nPatRows[nPat]); - pSndFile->Patterns[nPat].SetSignature(nPatRowsPerBeat[nPat], nPatRowsPerMeasure[nPat]); + pSndFile->Patterns[nPat].SetData(patternSettings[nPat].data, patternSettings[nPat].numRows); + pSndFile->Patterns[nPat].SetSignature(patternSettings[nPat].rowsPerBeat, patternSettings[nPat].rowsPerMeasure); + pSndFile->Patterns[nPat].SetName(patternSettings[nPat].name); } - - delete[] lpszpatnames; } END_CRITICAL(); EndWaitCursor(); Modified: trunk/OpenMPT/mptrack/Ctrl_pat.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/Ctrl_pat.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -149,7 +149,7 @@ m_EditSequence.SetParent(this); m_EditSpacing.SetParent(this); m_EditPatName.SetParent(this); - m_EditPatName.SetLimitText(MAX_PATTERNNAME); + m_EditPatName.SetLimitText(MAX_PATTERNNAME - 1); m_EditOrderListMargins.SetParent(this); m_EditOrderListMargins.SetLimitText(3); // Spin controls @@ -328,7 +328,7 @@ nPat = (PATTERNINDEX)(dwHintMask >> HINT_SHIFT_PAT); else nPat = (PATTERNINDEX)SendViewMessage(VIEWMSG_GETCURRENTPATTERN); - m_pSndFile->GetPatternName(nPat, s, sizeof(s)); + m_pSndFile->Patterns[nPat].GetName(s, CountOf(s)); m_EditPatName.SetWindowText(s); BOOL bXMIT = (m_pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT)) ? TRUE : FALSE; m_ToolBar.EnableButton(ID_PATTERN_MIDIMACRO, bXMIT); @@ -1071,13 +1071,15 @@ PATTERNINDEX nPat = (PATTERNINDEX)SendViewMessage(VIEWMSG_GETCURRENTPATTERN); m_EditPatName.GetWindowText(s, MAX_PATTERNNAME); - s[MAX_PATTERNNAME-1] = 0; - m_pSndFile->GetPatternName(nPat, sold, sizeof(sold)); + s[MAX_PATTERNNAME - 1] = 0; + m_pSndFile->Patterns[nPat].GetName(sold, CountOf(sold)); if (strcmp(s, sold)) { - m_pSndFile->SetPatternName(nPat, s); - if (m_pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT)) m_pModDoc->SetModified(); - m_pModDoc->UpdateAllViews(NULL, (nPat << HINT_SHIFT_PAT) | HINT_PATNAMES, this); + if(m_pSndFile->Patterns[nPat].SetName(s)) + { + if (m_pSndFile->m_nType & (MOD_TYPE_XM|MOD_TYPE_IT|MOD_TYPE_MPT)) m_pModDoc->SetModified(); + m_pModDoc->UpdateAllViews(NULL, (nPat << HINT_SHIFT_PAT) | HINT_PATNAMES, this); + } } } } Modified: trunk/OpenMPT/mptrack/Ctrl_seq.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/Ctrl_seq.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -493,6 +493,7 @@ if (nCurNdx >= pSndFile->Patterns.Size()) nCurNdx = 0; nCurNdx = nCurNdx * 10 + static_cast<PATTERNINDEX>(enterNum); + STATIC_ASSERT(MAX_PATTERNS < 10000); if ((nCurNdx >= 1000) && (nCurNdx > nMaxNdx)) nCurNdx %= 1000; if ((nCurNdx >= 100) && (nCurNdx > nMaxNdx)) nCurNdx %= 100; if ((nCurNdx >= 10) && (nCurNdx > nMaxNdx)) nCurNdx %= 10; @@ -732,10 +733,10 @@ if (m_nScrollPos < pSndFile->Order.GetLength()) { PATTERNINDEX nPat = pSndFile->Order[m_nScrollPos]; - if ((nPat < pSndFile->Patterns.Size()) && (nPat < pSndFile->m_nPatternNames)) + if (nPat < pSndFile->Patterns.Size()) { - CHAR szpat[40] = ""; - if (pSndFile->GetPatternName(nPat, szpat)) + CHAR szpat[MAX_PATTERNNAME] = ""; + if (pSndFile->Patterns[nPat].GetName(szpat, MAX_PATTERNNAME) && strlen(szpat)) { wsprintf(s+strlen(s), ": %s", szpat); } Modified: trunk/OpenMPT/mptrack/MPTHacks.cpp =================================================================== --- trunk/OpenMPT/mptrack/MPTHacks.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/MPTHacks.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -163,26 +163,18 @@ } // Check for pattern names - foundHere = false; - for(PATTERNINDEX i = 0; i < m_SndFile.GetNumPatterns(); i++) + if(m_SndFile.Patterns.GetNumNamedPatterns() > 0) { - if(m_SndFile.Patterns.IsValidPat(i)) + AddToLog("Found pattern names\n"); + foundHacks = true; + if(autofix) { - TCHAR tempname[MAX_PATTERNNAME]; - MemsetZero(tempname); - m_SndFile.GetPatternName(i, tempname, sizeof(tempname)); - if(strcmp(tempname, "") != 0) + for(PATTERNINDEX i = 0; i < m_SndFile.GetNumPatterns(); i++) { - foundHere = foundHacks = true; - if(autofix) - m_SndFile.SetPatternName(i, ""); - else - break; + m_SndFile.Patterns[i].SetName(""); } } } - if(foundHere) - AddToLog("Found pattern names\n"); // Check for too many channels if(m_SndFile.GetNumChannels() > originalSpecs->channelsMax || m_SndFile.GetNumChannels() < originalSpecs->channelsMin) Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -628,7 +628,6 @@ if ((nPat < m_SndFile.Patterns.Size()) && (m_SndFile.Patterns[nPat])) { BEGIN_CRITICAL(); - m_SndFile.SetPatternName(nPat, ""); m_SndFile.Patterns.Remove(nPat); END_CRITICAL(); SetModified(); Modified: trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp =================================================================== --- trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -427,8 +427,8 @@ SetDlgItemText(IDC_TEXT1, s); // Window title - CHAR szName[MAX_PATTERNNAME + 2]; - pSndFile->GetPatternName(m_nPattern, szName, MAX_PATTERNNAME); + CHAR szName[MAX_PATTERNNAME + 1]; + pSndFile->Patterns[m_nPattern].GetName(szName, MAX_PATTERNNAME); if(strlen(szName)) { strcat(szName, ")"); Modified: trunk/OpenMPT/mptrack/View_tre.cpp =================================================================== --- trunk/OpenMPT/mptrack/View_tre.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/mptrack/View_tre.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -805,7 +805,7 @@ if (pSndFile->Order.GetSequence(nSeq)[iOrd] < pSndFile->Patterns.Size()) { stmp[0] = 0; - pSndFile->GetPatternName(pSndFile->Order.GetSequence(nSeq)[iOrd], stmp, sizeof(stmp)); + pSndFile->Patterns[pSndFile->Order.GetSequence(nSeq)[iOrd]].GetName(stmp, CountOf(stmp)); if (stmp[0]) { wsprintf(s, (CMainFrame::m_dwPatternSetup & PATTERN_HEXDISPLAY) ? "[%02Xh] %d: %s" : "[%02d] %d: %s", @@ -866,7 +866,7 @@ if (pSndFile->Patterns[iPat]) { stmp[0] = 0; - pSndFile->GetPatternName(iPat, stmp, sizeof(stmp)); + pSndFile->Patterns[iPat].GetName(stmp, CountOf(stmp)); if (stmp[0]) { wsprintf(s, "%d: %s", iPat, stmp); Modified: trunk/OpenMPT/soundlib/Load_ams.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_ams.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_ams.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -146,19 +146,20 @@ } // Read Pattern Names - m_lpszPatternNames = new char[pfh->patterns * 32]; - if (!m_lpszPatternNames) return true; - m_nPatternNames = pfh->patterns; - memset(m_lpszPatternNames, 0, m_nPatternNames * 32); - for (UINT pNam=0; pNam < m_nPatternNames; pNam++) + for (UINT pNam = 0; pNam < pfh->patterns; pNam++) { - if (dwMemPos + 32 >= dwMemLength) return true; + if (dwMemPos + 1 >= dwMemLength) return true; tmp = lpStream[dwMemPos++]; - tmp2 = (tmp < 32) ? tmp : 31; - if (tmp2) memcpy(m_lpszPatternNames+pNam*32, lpStream+dwMemPos, tmp2); + tmp2 = min(tmp, MAX_PATTERNNAME - 1); // not counting null char + if (dwMemPos + tmp >= dwMemLength) return true; + Patterns.Insert(pNam, 64); // Create pattern now, so that the name won't be overwritten later. + if(tmp2) + { + Patterns[pNam].SetName((char *)(lpStream + dwMemPos), tmp2 + 1); + } dwMemPos += tmp; } - + // Read Song Comments tmp = *((WORD *)(lpStream+dwMemPos)); dwMemPos += 2; @@ -183,7 +184,7 @@ UINT len = *((DWORD *)(lpStream + dwMemPos)); dwMemPos += 4; if ((len >= dwMemLength) || (dwMemPos + len > dwMemLength)) return true; - Patterns.Insert(iPat, 64); + // Pattern has been inserted when reading pattern names MODCOMMAND* m = Patterns[iPat]; if (!m) return true; const BYTE *p = lpStream + dwMemPos; Modified: trunk/OpenMPT/soundlib/Load_it.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_it.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -465,6 +465,18 @@ } +void CopyPatternName(CPattern &pattern, char **patNames, UINT &patNamesLen) +//------------------------------------------------------------------------- +{ + if(*patNames != nullptr && patNamesLen > 0) + { + pattern.SetName(*patNames, min(MAX_PATTERNNAME, patNamesLen)); + *patNames += MAX_PATTERNNAME; + patNamesLen -= min(MAX_PATTERNNAME, patNamesLen); + } +} + + bool CSoundFile::ReadIT(const LPCBYTE lpStream, const DWORD dwMemLength) //---------------------------------------------------------------------- { @@ -809,19 +821,16 @@ } // Read pattern names: "PNAM" + char *patNames = nullptr; + UINT patNamesLen = 0; if ((dwMemPos + 8 < dwMemLength) && (*((DWORD *)(lpStream+dwMemPos)) == 0x4d414e50)) { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); + patNamesLen = *((DWORD *)(lpStream + dwMemPos + 4)); dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= patpos.size()*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) + if ((dwMemPos + patNamesLen <= dwMemLength) && (patNamesLen > 0)) { - m_lpszPatternNames = new char[len]; - if (m_lpszPatternNames) - { - m_nPatternNames = len / MAX_PATTERNNAME; - memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); - } - dwMemPos += len; + patNames = (char *)(lpStream + dwMemPos); + dwMemPos += patNamesLen; } } @@ -923,6 +932,8 @@ if (i >= len) break; } } + + // Reading Instruments m_nInstruments = 0; if (pifh->flags & 0x04) m_nInstruments = pifh->insnum; @@ -1061,6 +1072,8 @@ #endif // MODPLUG_TRACKER break; } + // Now (after the Insert() call), we can read the pattern name. + CopyPatternName(Patterns[npat], &patNames, patNamesLen); continue; } UINT len = *((WORD *)(lpStream+patpos[npat])); @@ -1070,6 +1083,9 @@ if(Patterns.Insert(npat, rows)) continue; + // Now (after the Insert() call), we can read the pattern name. + CopyPatternName(Patterns[npat], &patNames, patNamesLen); + memset(lastvalue, 0, sizeof(lastvalue)); memset(chnmask, 0, sizeof(chnmask)); MODCOMMAND *m = Patterns[npat]; @@ -1469,12 +1485,10 @@ dwExtra += sizeof(MODMIDICFG); } // Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) + const PATTERNINDEX numNamedPats = Patterns.GetNumNamedPatterns(); + if (numNamedPats > 0) { - dwPatNamLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwPatNamLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwPatNamLen-MAX_PATTERNNAME])) dwPatNamLen -= MAX_PATTERNNAME; - if (dwPatNamLen < MAX_PATTERNNAME) dwPatNamLen = 0; - if (dwPatNamLen) dwExtra += dwPatNamLen + 8; + dwExtra += (numNamedPats * MAX_PATTERNNAME) + 8; } // Mix Plugins dwExtra += SaveMixPlugins(NULL, TRUE); @@ -1500,14 +1514,22 @@ fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); } // Writing pattern names - if (dwPatNamLen) + if (numNamedPats) { DWORD d = 0x4d414e50; fwrite(&d, 1, 4, f); - fwrite(&dwPatNamLen, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwPatNamLen, f); + d = numNamedPats * MAX_PATTERNNAME; + fwrite(&d, 1, 4, f); + + for(PATTERNINDEX nPat = 0; nPat < numNamedPats; nPat++) + { + char name[MAX_PATTERNNAME]; + MemsetZero(name); + Patterns[nPat].GetName(name, MAX_PATTERNNAME); + fwrite(name, 1, MAX_PATTERNNAME, f); + } } - // Writing channel Names + // Writing channel names if (dwChnNamLen) { DWORD d = 0x4d414e43; Modified: trunk/OpenMPT/soundlib/Load_itp.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_itp.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_itp.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -230,25 +230,19 @@ // m_nPatternNames memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); - m_nPatternNames = id; + const PATTERNINDEX numNamedPats = id; dwMemPos += sizeof(DWORD); // pattern name string length (=MAX_PATTERNNAME) memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); - len = id; + const DWORD patNameLen = id; 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+dwMemPos,m_nPatternNames * len); - } - else return false; + ASSERT_CAN_READ(numNamedPats * patNameLen); + char *patNames = (char *)(lpStream + dwMemPos); + dwMemPos += numNamedPats * patNameLen; - dwMemPos += m_nPatternNames * len; - // modcommand data length ASSERT_CAN_READ(4); memcpy(&id,lpStream+dwMemPos,sizeof(DWORD)); @@ -275,6 +269,11 @@ dwMemPos += m_nChannels * Patterns[npat].GetNumRows() * n; continue; } + if(npat < numNamedPats && patNameLen > 0) + { + Patterns[npat].SetName(patNames, patNameLen); + patNames += patNameLen; + } // Pattern data long datasize = m_nChannels * Patterns[npat].GetNumRows() * n; @@ -583,7 +582,7 @@ fwrite(&id, 1, sizeof(id), f); // order array - Order.WriteAsByte(f, MAX_ORDERS); + Order.WriteAsByte(f, id); // Song Patterns @@ -592,13 +591,22 @@ fwrite(&id, 1, sizeof(id), f); // number of pattern name strings - id = m_nPatternNames; + PATTERNINDEX numNamedPats = Patterns.GetNumNamedPatterns(); + numNamedPats = min(numNamedPats, MAX_PATTERNS); + id = numNamedPats; 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); + // pattern name string + for(PATTERNINDEX nPat = 0; nPat < numNamedPats; nPat++) + { + char name[MAX_PATTERNNAME]; + MemsetZero(name); + Patterns[nPat].GetName(name, MAX_PATTERNNAME); + fwrite(name, 1, MAX_PATTERNNAME, f); + } // modcommand data length id = sizeof(MODCOMMAND_ORIGINAL); Modified: trunk/OpenMPT/soundlib/Load_med.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_med.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -867,7 +867,7 @@ UINT namelen = BigEndian(pbi->blocknamelen); if ((nameofs < dwMemLength) && (namelen < dwMemLength - nameofs)) { - SetPatternName(iBlk, (LPCSTR)(lpStream+nameofs)); + Patterns[iBlk].SetName((char *)(lpStream + nameofs), namelen); } } if (pbi->cmdexttable) Modified: trunk/OpenMPT/soundlib/Load_mid.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_mid.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_mid.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -760,7 +760,7 @@ } else if (!trk) { - SetPatternName(pat, s); + Patterns[pat].SetName(s); } #ifdef MIDI_LOG Log("Track #%d, META 0x%02X, Pattern %d: ", trk, i, pat); Modified: trunk/OpenMPT/soundlib/Load_psm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_psm.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_psm.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -766,7 +766,7 @@ // set the subsong name to all pattern names for(PATTERNINDEX nPat = startPattern; nPat <= endPattern; nPat++) { - SetPatternName(nPat, subsongs[i].songName); + Patterns[nPat].SetName(subsongs[i].songName); } // subsongs with different panning setup -> write to pattern (MUSIC_C.PSM) Modified: trunk/OpenMPT/soundlib/Load_xm.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_xm.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Load_xm.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -625,15 +625,15 @@ // Read pattern names: "PNAM" if ((dwMemPos + 8 < dwMemLength) && (LittleEndian(*((DWORD *)(lpStream+dwMemPos))) == 0x4d414e50)) { - UINT len = *((DWORD *)(lpStream+dwMemPos+4)); + UINT len = *((DWORD *)(lpStream + dwMemPos + 4)); dwMemPos += 8; - if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS*MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) + if ((dwMemPos + len <= dwMemLength) && (len <= MAX_PATTERNS * MAX_PATTERNNAME) && (len >= MAX_PATTERNNAME)) { - m_lpszPatternNames = new char[len]; - if (m_lpszPatternNames) + DWORD pos = 0; + PATTERNINDEX nPat = 0; + for(pos = 0; pos < len; pos += MAX_PATTERNNAME, nPat++) { - m_nPatternNames = len / MAX_PATTERNNAME; - memcpy(m_lpszPatternNames, lpStream+dwMemPos, len); + Patterns[nPat].SetName((char *)(lpStream + dwMemPos + pos), min(MAX_PATTERNNAME, len - pos)); } dwMemPos += len; } @@ -1100,16 +1100,20 @@ fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); } // Writing Pattern Names - if ((m_nPatternNames) && (m_lpszPatternNames)) + const PATTERNINDEX numNamedPats = Patterns.GetNumNamedPatterns(); + if (numNamedPats > 0) { - DWORD dwLen = m_nPatternNames * MAX_PATTERNNAME; - while ((dwLen >= MAX_PATTERNNAME) && (!m_lpszPatternNames[dwLen-MAX_PATTERNNAME])) dwLen -= MAX_PATTERNNAME; - if (dwLen >= MAX_PATTERNNAME) + DWORD dwLen = numNamedPats * MAX_PATTERNNAME; + DWORD d = 0x4d414e50; + fwrite(&d, 1, 4, f); + fwrite(&dwLen, 1, 4, f); + + for(PATTERNINDEX nPat = 0; nPat < numNamedPats; nPat++) { - DWORD d = 0x4d414e50; - fwrite(&d, 1, 4, f); - fwrite(&dwLen, 1, 4, f); - fwrite(m_lpszPatternNames, 1, dwLen, f); + char name[MAX_PATTERNNAME]; + MemsetZero(name); + Patterns[nPat].GetName(name, MAX_PATTERNNAME); + fwrite(name, 1, MAX_PATTERNNAME, f); } } // Writing Channel Names Modified: trunk/OpenMPT/soundlib/Sndfile.cpp =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Sndfile.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -455,8 +455,6 @@ m_nMixChannels = 0; m_nSamples = 0; m_nInstruments = 0; - m_nPatternNames = 0; - m_lpszPatternNames = NULL; m_lpszSongComments = nullptr; m_nFreqFactor = m_nTempoFactor = 128; m_nMasterVolume = 128; @@ -547,9 +545,7 @@ m_nMaxPeriod = 32767; m_nSamplePreAmp = 48; m_nVSTiVolume = 48; - m_nPatternNames = 0; m_nMaxOrderPosition = 0; - m_lpszPatternNames = NULL; m_lpszSongComments = nullptr; m_nMixLevels = mixLevels_compatible; // Will be overridden if appropriate. memset(Samples, 0, sizeof(Samples)); @@ -853,11 +849,7 @@ { size_t i; Patterns.DestroyPatterns(); - m_nPatternNames = 0; - delete[] m_lpszPatternNames; - m_lpszPatternNames = NULL; - FreeMessage(); for (i=1; i<MAX_SAMPLES; i++) @@ -2477,51 +2469,6 @@ } -BOOL CSoundFile::SetPatternName(PATTERNINDEX nPat, LPCSTR lpszName) -//------------------------------------------------------------------ -{ - CHAR szName[MAX_PATTERNNAME] = ""; - if (nPat >= Patterns.Size()) return FALSE; - if (lpszName) lstrcpyn(szName, lpszName, MAX_PATTERNNAME); - SpaceToNullString(szName); //szName[MAX_PATTERNNAME-1] = 0; - if (!m_lpszPatternNames) m_nPatternNames = 0; - if (nPat >= m_nPatternNames) - { - //if (!lpszName[0]) return TRUE; - UINT len = (nPat+1)*MAX_PATTERNNAME; - CHAR *p = new CHAR[len]; - if (!p) return FALSE; - memset(p, 0, len); - if (m_lpszPatternNames) - { - memcpy(p, m_lpszPatternNames, m_nPatternNames * MAX_PATTERNNAME); - delete[] m_lpszPatternNames; - m_lpszPatternNames = NULL; - } - m_lpszPatternNames = p; - m_nPatternNames = nPat + 1; - } - memcpy(m_lpszPatternNames + nPat * MAX_PATTERNNAME, szName, MAX_PATTERNNAME); - return TRUE; -} - - -BOOL CSoundFile::GetPatternName(PATTERNINDEX nPat, LPSTR lpszName, UINT cbSize) const -//----------------------------------------------------------------------------------- -{ - if ((!lpszName) || (!cbSize)) return FALSE; - lpszName[0] = 0; - if (cbSize > MAX_PATTERNNAME) cbSize = MAX_PATTERNNAME; - if ((m_lpszPatternNames) && (nPat < m_nPatternNames)) - { - memcpy(lpszName, m_lpszPatternNames + nPat * MAX_PATTERNNAME, cbSize); - lpszName[cbSize-1] = 0; - return TRUE; - } - return FALSE; -} - - #ifndef FASTSOUNDLIB // Check whether a sample is used. @@ -2572,7 +2519,7 @@ } -// Detect samples are are referenced by an instrument, but actually not used in a song. +// Detect samples that are referenced by an instrument, but actually not used in a song. // Only works in instrument mode. Unused samples are marked as false in the vector. SAMPLEINDEX CSoundFile::DetectUnusedSamples(vector<bool> &sampleUsed) const //------------------------------------------------------------------------- @@ -2737,8 +2684,8 @@ void CSoundFile::DeleteStaticdata() //--------------------------------- { - delete s_pTuningsSharedLocal; s_pTuningsSharedLocal = 0; - delete s_pTuningsSharedBuiltIn; s_pTuningsSharedBuiltIn = 0; + delete s_pTuningsSharedLocal; s_pTuningsSharedLocal = nullptr; + delete s_pTuningsSharedBuiltIn; s_pTuningsSharedBuiltIn = nullptr; } bool CSoundFile::SaveStaticTunings() Modified: trunk/OpenMPT/soundlib/Sndfile.h =================================================================== --- trunk/OpenMPT/soundlib/Sndfile.h 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/Sndfile.h 2011-05-15 20:26:20 UTC (rev 873) @@ -653,8 +653,8 @@ 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; - LPSTR m_lpszSongComments, m_lpszPatternNames; + UINT m_nMaxOrderPosition; + LPSTR m_lpszSongComments; UINT ChnMix[MAX_CHANNELS]; // Channels to be mixed MODCHANNEL Chn[MAX_CHANNELS]; // Mixing channels... First m_nChannel channels are master channels (i.e. they are never NNA channels)! MODCHANNELSETTINGS ChnSettings[MAX_BASECHANNELS]; // Initial channels settings @@ -740,8 +740,6 @@ bool IsPaused() const { return (m_dwSongFlags & (SONG_PAUSED|SONG_STEP)) ? true : false; } // Added SONG_STEP as it seems to be desirable in most cases to check for this as well. void LoopPattern(PATTERNINDEX nPat, ROWINDEX nRow = 0); void CheckCPUUsage(UINT nCPU); - BOOL SetPatternName(PATTERNINDEX nPat, LPCSTR lpszName); - BOOL GetPatternName(PATTERNINDEX nPat, LPSTR lpszName, UINT cbSize=MAX_PATTERNNAME) const; void SetupITBidiMode(); @@ -928,7 +926,7 @@ DWORD IsSongFinished(UINT nOrder, UINT nRow) const; void UpdateTimeSignature(); - UINT GetNumTicksOnCurrentRow() { return m_nMusicSpeed * (m_nPatternDelay + 1) + m_nFrameDelay; }; + UINT GetNumTicksOnCurrentRow() const { return m_nMusicSpeed * (m_nPatternDelay + 1) + m_nFrameDelay; }; public: // Write pattern effect functions bool TryWriteEffect(PATTERNINDEX nPat, ROWINDEX nRow, BYTE nEffect, BYTE nParam, bool bIsVolumeEffect, CHANNELINDEX nChn = CHANNELINDEX_INVALID, bool bAllowMultipleEffects = true, writeEffectAllowRowChange allowRowChange = weIgnore, bool bRetry = true); Modified: trunk/OpenMPT/soundlib/pattern.cpp =================================================================== --- trunk/OpenMPT/soundlib/pattern.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/pattern.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -126,6 +126,7 @@ m_Rows = m_RowsPerBeat = m_RowsPerMeasure = 0; FreePattern(m_ModCommands); m_ModCommands = nullptr; + m_PatternName.Empty(); //END_CRITICAL(); } @@ -211,6 +212,38 @@ } +bool CPattern::SetName(char *newName, size_t maxChars) +//---------------------------------------------------- +{ + if(newName == nullptr || maxChars == 0) + { + return false; + } + m_PatternName.SetString(newName, maxChars - 1); + return true; +} + + +bool CPattern::GetName(char *buffer, size_t maxChars) const +//--------------------------------------------------------- +{ + if(buffer == nullptr || maxChars == 0) + { + return false; + } + strncpy(buffer, m_PatternName, maxChars - 1); + buffer[maxChars - 1] = '\0'; + return true; +} + + +//////////////////////////////////////////////////////////////////////// +// +// Static allocation / deallocation methods +// +//////////////////////////////////////////////////////////////////////// + + MODCOMMAND *CPattern::AllocatePattern(ROWINDEX rows, CHANNELINDEX nchns) //---------------------------------------------------------------------- { @@ -227,6 +260,13 @@ } +//////////////////////////////////////////////////////////////////////// +// +// ITP functions +// +//////////////////////////////////////////////////////////////////////// + + bool CPattern::WriteITPdata(FILE* f) const //---------------------------------------- { Modified: trunk/OpenMPT/soundlib/pattern.h =================================================================== --- trunk/OpenMPT/soundlib/pattern.h 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/pattern.h 2011-05-15 20:26:20 UTC (rev 873) @@ -30,6 +30,7 @@ m_Rows = pat.m_Rows; m_RowsPerBeat = pat.m_RowsPerBeat; m_RowsPerMeasure = pat.m_RowsPerMeasure; + m_PatternName = pat.m_PatternName; return *this; } //END: OPERATORS @@ -71,6 +72,12 @@ bool SetSignature(const ROWINDEX rowsPerBeat, const ROWINDEX rowsPerMeasure); void RemoveSignature() { m_RowsPerBeat = m_RowsPerMeasure = 0; } + // Patter name functions (for both CString and char[] arrays) - bool functions return true on success. + bool SetName(char *newName, size_t maxChars = MAX_PATTERNNAME); + bool SetName(CString newName) { m_PatternName = newName; return true; }; + bool GetName(char *buffer, size_t maxChars = MAX_PATTERNNAME) const; + CString GetName() const { return m_PatternName; }; + // Double number of rows bool Expand(); @@ -117,6 +124,7 @@ ROWINDEX m_Rows; ROWINDEX m_RowsPerBeat; // patterns-specific time signature. if != 0, this is implicitely set. ROWINDEX m_RowsPerMeasure; // dito + CString m_PatternName; CPatternContainer& m_rPatternContainer; //END: DATA }; Modified: trunk/OpenMPT/soundlib/patternContainer.cpp =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.cpp 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/patternContainer.cpp 2011-05-15 20:26:20 UTC (rev 873) @@ -61,9 +61,10 @@ { CPattern::FreePattern(m_Patterns[index].m_ModCommands); } - m_Patterns[index].m_ModCommands = CPattern::AllocatePattern(rows, m_rSndFile.m_nChannels); + m_Patterns[index].m_ModCommands = CPattern::AllocatePattern(rows, m_rSndFile.GetNumChannels()); m_Patterns[index].m_Rows = rows; m_Patterns[index].RemoveSignature(); + m_Patterns[index].SetName(""); if(!m_Patterns[index]) return true; @@ -153,6 +154,25 @@ } +PATTERNINDEX CPatternContainer::GetNumNamedPatterns() const +//--------------------------------------------------------- +{ + if(Size() == 0) + { + return 0; + } + for(PATTERNINDEX nPat = Size(); nPat > 0; nPat--) + { + if(m_Patterns[nPat - 1].GetName() != "") + { + return nPat; + } + } + return 0; +} + + + void WriteModPatterns(std::ostream& oStrm, const CPatternContainer& patc) //---------------------------------------------------------------------- { Modified: trunk/OpenMPT/soundlib/patternContainer.h =================================================================== --- trunk/OpenMPT/soundlib/patternContainer.h 2011-05-13 16:02:13 UTC (rev 872) +++ trunk/OpenMPT/soundlib/patternContainer.h 2011-05-15 20:26:20 UTC (rev 873) @@ -76,6 +76,9 @@ void OnModTypeChanged(const MODTYPE oldtype); + // Returns index of highest pattern with pattern named + 1. + PATTERNINDEX GetNumNamedPatterns() const; + //END: INTERFACE METHODS This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |