From: <sag...@us...> - 2012-04-27 20:05:33
|
Revision: 1255 http://modplug.svn.sourceforge.net/modplug/?rev=1255&view=rev Author: saga-games Date: 2012-04-27 20:05:26 +0000 (Fri, 27 Apr 2012) Log Message: ----------- [Fix] Some small errors in S3M saver. [Imp] Default global volume is now written to pattern when converting to XM and is detected as an MPT extension in "Detect MPT hacks". [Ref] Smaller stuff. Modified Paths: -------------- trunk/OpenMPT/mptrack/Ctrl_gen.cpp trunk/OpenMPT/mptrack/MPTHacks.cpp trunk/OpenMPT/mptrack/ModConvert.cpp trunk/OpenMPT/mptrack/ModConvert.h trunk/OpenMPT/mptrack/Moddoc.cpp trunk/OpenMPT/mptrack/Moddoc.h trunk/OpenMPT/mptrack/Modedit.cpp trunk/OpenMPT/mptrack/Moptions.cpp trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp trunk/OpenMPT/soundlib/Load_s3m.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_gen.cpp =================================================================== --- trunk/OpenMPT/mptrack/Ctrl_gen.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/Ctrl_gen.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -230,14 +230,15 @@ const BOOL bIsNotMOD = (m_pSndFile->GetType() != MOD_TYPE_MOD); const BOOL bIsNotMOD_S3M = ((bIsNotMOD) && (m_pSndFile->GetType() != MOD_TYPE_S3M)); + const BOOL bIsNotMOD_XM = ((bIsNotMOD) && (m_pSndFile->GetType() != MOD_TYPE_XM)); m_EditTempo.EnableWindow(bIsNotMOD); m_SpinTempo.EnableWindow(bIsNotMOD); m_SliderTempo.EnableWindow(bIsNotMOD); m_EditSpeed.EnableWindow(bIsNotMOD); m_SpinSpeed.EnableWindow(bIsNotMOD); - m_SliderGlobalVol.EnableWindow(bIsNotMOD); - m_EditGlobalVol.EnableWindow(bIsNotMOD); - m_SpinGlobalVol.EnableWindow(bIsNotMOD); + m_SliderGlobalVol.EnableWindow(bIsNotMOD_XM); + m_EditGlobalVol.EnableWindow(bIsNotMOD_XM); + m_SpinGlobalVol.EnableWindow(bIsNotMOD_XM); m_EditSamplePA.EnableWindow(bIsNotMOD); m_SpinSamplePA.EnableWindow(bIsNotMOD); //m_SliderSamplePreAmp.EnableWindow(bIsNotMOD); Modified: trunk/OpenMPT/mptrack/MPTHacks.cpp =================================================================== --- trunk/OpenMPT/mptrack/MPTHacks.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/MPTHacks.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -64,7 +64,7 @@ } } else if(type == MOD_TYPE_IT) // ModPlug IT extensions { - if((m.command == CMD_S3MCMDEX) && ((m.param >> 4) == 0x09) && (m.param != 0x91)) + if((m.command == CMD_S3MCMDEX) && ((m.param & 0xF0) == 0x90) && (m.param != 0x91)) { *foundHacks = true; if(autofix) @@ -220,6 +220,17 @@ } } + // Global volume + if(m_SndFile.GetType() == MOD_TYPE_XM && m_SndFile.m_nDefaultGlobalVolume != MAX_GLOBAL_VOLUME) + { + foundHacks = true; + AddToLog("XM format does not support default global volume"); + if(autofix) + { + GlobalVolumeToPattern(); + } + } + // Pattern count if(m_SndFile.Patterns.GetNumPatterns() > originalSpecs->patternsMax) { Modified: trunk/OpenMPT/mptrack/ModConvert.cpp =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/ModConvert.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -85,7 +85,7 @@ const MODTYPE nOldType = m_SndFile.GetType(); - if (nNewType == nOldType && nNewType == MOD_TYPE_IT) + if(nNewType == nOldType && nNewType == MOD_TYPE_IT) { // Even if m_nType doesn't change, we might need to change extension in itp<->it case. // This is because ITP is a HACK and doesn't genuinely change m_nType, @@ -222,7 +222,7 @@ m->param = cEffectMemory[channel][m->command]; else cEffectMemory[channel][m->command] = m->param; - break; + break; } } @@ -498,6 +498,15 @@ { ConvertSamplesToInstruments(); } + + // XM has no global volume + if(newTypeIsXM && m_SndFile.m_nDefaultGlobalVolume != MAX_GLOBAL_VOLUME) + { + if(!GlobalVolumeToPattern()) + { + CHANGEMODTYPE_WARNING(wGlobalVolumeNotSupported); + } + } // Pattern warnings CHAR s[64]; @@ -530,6 +539,7 @@ CHANGEMODTYPE_CHECK(wEditHistory, "Edit history will not be saved in the new format.\n"); CHANGEMODTYPE_CHECK(wMixmode, "Consider setting the mix levels to \"Compatible\" in the song properties when working with legacy formats.\n"); CHANGEMODTYPE_CHECK(wCompatibilityMode, "Consider enabling the \"compatible playback\" option in the song properties to increase compatiblity with other players.\n"); + CHANGEMODTYPE_CHECK(wGlobalVolumeNotSupported, "Default global volume is not supported by the new format.\n"); SetModified(); GetPatternUndo().ClearUndo(); Modified: trunk/OpenMPT/mptrack/ModConvert.h =================================================================== --- trunk/OpenMPT/mptrack/ModConvert.h 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/ModConvert.h 2012-04-27 20:05:26 UTC (rev 1255) @@ -35,5 +35,6 @@ wMixmode, wCompatibilityMode, wPitchToTempoLock, + wGlobalVolumeNotSupported, wNumWarnings }; Modified: trunk/OpenMPT/mptrack/Moddoc.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/Moddoc.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -873,8 +873,8 @@ } -UINT CModDoc::GetPlaybackMidiChannel(const ModInstrument *pIns, CHANNELINDEX nChn) const -//-------------------------------------------------------------------------------------- +uint8 CModDoc::GetPlaybackMidiChannel(const ModInstrument *pIns, CHANNELINDEX nChn) const +//--------------------------------------------------------------------------------------- { if(pIns->nMidiChannel == MidiMappedChannel) { @@ -1025,7 +1025,7 @@ if ((!nPlugin || nPlugin > MAX_MIXPLUGINS) && nCurrentChn != CHANNELINDEX_INVALID) nPlugin = m_SndFile.ChnSettings[nCurrentChn].nMixPlugin; // Then try Channel VST - if ((nPlugin) && (nPlugin <= MAX_MIXPLUGINS)) + if ((nPlugin) && (nPlugin <= MAX_MIXPLUGINS)) { IMixPlugin *pPlugin = m_SndFile.m_MixPlugins[nPlugin - 1].pMixPlugin; Modified: trunk/OpenMPT/mptrack/Moddoc.h =================================================================== --- trunk/OpenMPT/mptrack/Moddoc.h 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/Moddoc.h 2012-04-27 20:05:26 UTC (rev 1255) @@ -113,12 +113,15 @@ ///////////////////////////////////////////////////////////////////////// // Split Keyboard Settings (pattern editor) -#define SPLIT_OCTAVE_RANGE 9 - //========================== struct SplitKeyboardSettings //========================== { + enum + { + splitOctaveRange = 9, + }; + bool IsSplitActive() const { return (octaveLink && (octaveModifier != 0)) || (splitInstrument > 0) || (splitVolume != 0); } ModCommand::NOTE splitNote; ModCommand::INSTR splitInstrument; @@ -296,7 +299,9 @@ void LearnMacro(int macro, long param); void SetElapsedTime(ORDERINDEX nOrd, ROWINDEX nRow); + // Global settings to pattern effect conversion bool RestartPosToPattern(); + bool GlobalVolumeToPattern(); bool HasMPTHacks(const bool autofix = false); @@ -346,7 +351,7 @@ virtual void SetModifiedFlag(BOOL bModified=TRUE); //}}AFX_VIRTUAL - UINT GetPlaybackMidiChannel(const ModInstrument *pIns, CHANNELINDEX nChn) const; + uint8 GetPlaybackMidiChannel(const ModInstrument *pIns, CHANNELINDEX nChn) const; // Implementation Modified: trunk/OpenMPT/mptrack/Modedit.cpp =================================================================== --- trunk/OpenMPT/mptrack/Modedit.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/Modedit.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -919,3 +919,25 @@ m_SndFile.m_nRestartPos = 0; return result; } + + +// Convert module's default global volume to a pattern command. +bool CModDoc::GlobalVolumeToPattern() +//----------------------------------- +{ + bool result = false; + if(m_SndFile.GetModSpecifications().HasCommand(CMD_GLOBALVOLUME)) + { + for(ORDERINDEX i = 0; i < m_SndFile.Order.GetLength(); i++) + { + if(m_SndFile.TryWriteEffect(m_SndFile.Order[i], 0, CMD_GLOBALVOLUME, m_SndFile.m_nDefaultGlobalVolume * 64 / MAX_GLOBAL_VOLUME, false, CHANNELINDEX_INVALID, false, weTryNextRow)) + { + result = true; + break; + } + } + } + + m_SndFile.m_nDefaultGlobalVolume = MAX_GLOBAL_VOLUME; + return result; +} Modified: trunk/OpenMPT/mptrack/Moptions.cpp =================================================================== --- trunk/OpenMPT/mptrack/Moptions.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/Moptions.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -20,15 +20,13 @@ ////////////////////////////////////////////////////////////// // COptionsColors -typedef struct MPTCOLORDEF +static const struct ColorDescriptions { - LPCSTR pszName; - int nPreview; - UINT nColNdx1, nColNdx2, nColNdx3; - LPCSTR pszTxt1, pszTxt2, pszTxt3; -} MPTCOLORDEF; - -static MPTCOLORDEF gColorDefs[] = + char *name; + int previewImage; + uint32 colorIndex1, colorIndex2, colorIndex3; + char *descText1, *descText2, *descText3; +} colorDefs[] = { {"Pattern Editor", 0, MODCOLOR_BACKNORMAL, MODCOLOR_TEXTNORMAL, MODCOLOR_BACKHILIGHT, "Background:", "Foreground:", "Highlighted:"}, {"Active Row", 0, MODCOLOR_BACKCURROW, MODCOLOR_TEXTCURROW, 0, "Background:", "Foreground:", NULL}, @@ -92,9 +90,9 @@ CPropertyPage::OnInitDialog(); m_pPreviewDib = LoadDib(MAKEINTRESOURCE(IDB_COLORSETUP)); MemCopy(CustomColors, CMainFrame::GetSettings().rgbCustomColors); - for (UINT i = 0; i < CountOf(gColorDefs); i++) + for (UINT i = 0; i < CountOf(colorDefs); i++) { - m_ComboItem.SetItemData(m_ComboItem.AddString(gColorDefs[i].pszName), i); + m_ComboItem.SetItemData(m_ComboItem.AddString(colorDefs[i].name), i); } m_ComboItem.SetCurSel(0); m_BtnPreview.SetWindowPos(NULL, 0,0, PREVIEWBMP_WIDTH*2+2, PREVIEWBMP_HEIGHT*2+2, SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE); @@ -161,9 +159,9 @@ int nColor = -1; switch(nIdCtl) { - case IDC_BUTTON1: nColor = gColorDefs[m_nColorItem].nColNdx1; break; - case IDC_BUTTON2: nColor = gColorDefs[m_nColorItem].nColNdx2; break; - case IDC_BUTTON3: nColor = gColorDefs[m_nColorItem].nColNdx3; break; + case IDC_BUTTON1: nColor = colorDefs[m_nColorItem].colorIndex1; break; + case IDC_BUTTON2: nColor = colorDefs[m_nColorItem].colorIndex2; break; + case IDC_BUTTON3: nColor = colorDefs[m_nColorItem].colorIndex3; break; } if (!lpdis) return; if (nColor >= 0) @@ -193,7 +191,7 @@ } else if ((nIdCtl == IDC_BUTTON4) && (m_pPreviewDib)) { - int y = gColorDefs[m_nColorItem].nPreview; + int y = colorDefs[m_nColorItem].previewImage; RGBQUAD *p = m_pPreviewDib->bmiColors; if (IsDlgButtonChecked(IDC_CHECK2)) { @@ -302,21 +300,21 @@ void COptionsColors::OnSelectColor1() //----------------------------------- { - SelectColor(&CustomColors[gColorDefs[m_nColorItem].nColNdx1]); + SelectColor(&CustomColors[colorDefs[m_nColorItem].colorIndex1]); } void COptionsColors::OnSelectColor2() //----------------------------------- { - SelectColor(&CustomColors[gColorDefs[m_nColorItem].nColNdx2]); + SelectColor(&CustomColors[colorDefs[m_nColorItem].colorIndex2]); } void COptionsColors::OnSelectColor3() //----------------------------------- { - SelectColor(&CustomColors[gColorDefs[m_nColorItem].nColNdx3]); + SelectColor(&CustomColors[colorDefs[m_nColorItem].colorIndex3]); } @@ -340,11 +338,11 @@ void COptionsColors::OnUpdateDialog() //----------------------------------- { - MPTCOLORDEF *p = &gColorDefs[m_nColorItem]; - if (p->pszTxt1) m_TxtColor1.SetWindowText(p->pszTxt1); - if (p->pszTxt2) + const ColorDescriptions *p = &colorDefs[m_nColorItem]; + if (p->descText1) m_TxtColor1.SetWindowText(p->descText1); + if (p->descText2) { - m_TxtColor2.SetWindowText(p->pszTxt2); + m_TxtColor2.SetWindowText(p->descText2); m_TxtColor2.ShowWindow(SW_SHOW); m_BtnColor2.ShowWindow(SW_SHOW); m_BtnColor2.InvalidateRect(NULL, FALSE); @@ -353,9 +351,9 @@ m_TxtColor2.ShowWindow(SW_HIDE); m_BtnColor2.ShowWindow(SW_HIDE); } - if (p->pszTxt3) + if (p->descText3) { - m_TxtColor3.SetWindowText(p->pszTxt3); + m_TxtColor3.SetWindowText(p->descText3); m_TxtColor3.ShowWindow(SW_SHOW); m_BtnColor3.ShowWindow(SW_SHOW); m_BtnColor3.InvalidateRect(NULL, FALSE); @@ -538,24 +536,22 @@ END_MESSAGE_MAP() -struct OPTGENDESC +static const struct GeneralOptionsDescriptions { - DWORD dwFlagID; - LPCSTR pszListName, pszDescription; -}; - -static OPTGENDESC gOptGenDesc[] = + uint32 flag; + char *name, *description; +} generalOptionsList[] = { {PATTERN_PLAYNEWNOTE, "Play new notes while recording", "When this option is enabled, notes entered in the pattern editor will always be played (If not checked, notes won't be played in record mode)."}, {PATTERN_PLAYEDITROW, "Play whole row while recording", "When this option is enabled, all notes on the current row are played when entering notes in the pattern editor."}, - {PATTERN_CENTERROW, "Always center active row", "Turn on this option to have the active row always centered in the pattern editor (requires \"Always center active row\")."}, + {PATTERN_CENTERROW, "Always center active row", "Turn on this option to have the active row always centered in the pattern editor."}, {PATTERN_LARGECOMMENTS, "Use large font for comments", "With this option enabled, the song message editor will use a larger font."}, {PATTERN_HEXDISPLAY, "Display rows in hex", "With this option enabled, row numbers and sequence numbers will be displayed in hexadecimal."}, {PATTERN_WRAP, "Cursor wrap in pattern editor", "When this option is active, going past the end of a pattern row or channel will move the cursor to the beginning. When \"Continuous scroll\"-option is enabled, row wrap is disabled."}, {PATTERN_CREATEBACKUP, "Create backup files (*.bak)", "When this option is active, saving a file will create a backup copy of the original."}, - {PATTERN_DRAGNDROPEDIT, "Drag and Drop Editing", "Enable moving a selection in the pattern editor (copying if pressing shift while dragging)\n"}, + {PATTERN_DRAGNDROPEDIT, "Drag and Drop Editing", "Enable moving a selection in the pattern editor (copying if pressing shift while dragging)"}, {PATTERN_FLATBUTTONS, "Flat Buttons", "Use flat buttons in toolbars"}, - {PATTERN_SINGLEEXPAND, "Single click to expand tree", "Single-clicking in the left tree view will expand a branch"}, + {PATTERN_SINGLEEXPAND, "Single click to expand tree", "Single-clicking in the left tree view will expand a node."}, {PATTERN_MUTECHNMODE, "Ignored muted channels", "Notes will not be played on muted channels (unmuting will only start on a new note)."}, {PATTERN_NOEXTRALOUD, "No loud sample preview", "Disable loud playback of samples in the sample/instrument editor. Sample volume depends on the sample volume slider on the general tab when activated (if disabled, a sample volume of 256 is used)."}, {PATTERN_SHOWPREVIOUS, "Show Prev/Next patterns", "Displays grayed-out version of the previous/next patterns in the pattern editor. Does not work if \"always center active row\" is disabled."}, @@ -563,10 +559,10 @@ {PATTERN_KBDNOTEOFF, "Record note off", "Record note off when a key is released on the PC keyboard."}, {PATTERN_FOLLOWSONGOFF, "Follow song off by default", "Ensure follow song is off when opening or starting a new song."}, {PATTERN_MIDIRECORD, "MIDI record", "Enable MIDI in record by default."}, - {PATTERN_OLDCTXMENUSTYLE, "Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."}, + {PATTERN_OLDCTXMENUSTYLE, "Old style pattern context menu", "Check this option to hide unavailable items in the pattern editor context menu. Uncheck to grey-out unavailable items instead."}, {PATTERN_SYNCMUTE, "Maintain sample sync on mute", "Samples continue to be processed when channels are muted (like in IT2 and FT2)"}, {PATTERN_AUTODELAY, "Automatic delay commands", "Automatically insert appropriate note-delay commands when recording notes during live playback."}, - {PATTERN_NOTEFADE, "Note fade on key up", "Enable to fade / stop notes on key up in pattern tab." }, + {PATTERN_NOTEFADE, "Note fade on key up", "Enable to fade / stop notes on key up in pattern tab."}, {PATTERN_OVERFLOWPASTE, "Overflow paste mode", "Wrap pasted pattern data into next pattern. This is useful for creating echo channels."}, {PATTERN_RESETCHANNELS, "Reset channels on loop", "If enabled, channels will be reset to their initial state when song looping is enabled.\nNote: This does not affect manual song loops (i.e. triggered by pattern commands) and is recommended to be enabled."}, {PATTERN_LIVEUPDATETREE,"Update sample status in tree", "If enabled, active samples and instruments will be indicated by a different icon in the treeview."}, @@ -592,15 +588,15 @@ CHAR sname[32], s[256]; CPropertyPage::OnInitDialog(); - for (UINT i = 0; i < CountOf(gOptGenDesc); i++) + for(size_t i = 0; i < CountOf(generalOptionsList); i++) { wsprintf(sname, "Setup.Gen.Opt%d.Name", i + 1); if ((theApp.GetLocalizedString(sname, s, sizeof(s))) && (s[0])) m_CheckList.AddString(s); else - m_CheckList.AddString(gOptGenDesc[i].pszListName); + m_CheckList.AddString(generalOptionsList[i].name); - const int check = (CMainFrame::GetSettings().m_dwPatternSetup & gOptGenDesc[i].dwFlagID) != 0 ? BST_CHECKED : BST_UNCHECKED; + const int check = (CMainFrame::GetSettings().m_dwPatternSetup & generalOptionsList[i].flag) != 0 ? BST_CHECKED : BST_UNCHECKED; m_CheckList.SetCheck(i, check); } m_CheckList.SetCurSel(0); @@ -628,12 +624,12 @@ GetDlgItemText(IDC_OPTIONS_DIR_VSTS, szVstDir, _MAX_PATH); GetDlgItemText(IDC_OPTIONS_DIR_VSTPRESETS, szPresetDir, _MAX_PATH); - for (UINT i = 0; i < CountOf(gOptGenDesc); i++) + for(size_t i = 0; i < CountOf(generalOptionsList); i++) { const bool check = (m_CheckList.GetCheck(i) != BST_UNCHECKED); - if(check) CMainFrame::GetSettings().m_dwPatternSetup |= gOptGenDesc[i].dwFlagID; - else CMainFrame::GetSettings().m_dwPatternSetup &= ~gOptGenDesc[i].dwFlagID; + if(check) CMainFrame::GetSettings().m_dwPatternSetup |= generalOptionsList[i].flag; + else CMainFrame::GetSettings().m_dwPatternSetup &= ~generalOptionsList[i].flag; } CMainFrame *pMainFrm = CMainFrame::GetMainFrame(); @@ -683,9 +679,9 @@ CHAR sname[32], s[256]; LPCSTR pszDesc = NULL; const int sel = m_CheckList.GetCurSel(); - if ((sel >= 0) && (sel < CountOf(gOptGenDesc))) + if ((sel >= 0) && (sel < CountOf(generalOptionsList))) { - pszDesc = gOptGenDesc[sel].pszDescription; + pszDesc = generalOptionsList[sel].description; wsprintf(sname, "Setup.Gen.Opt%d.Desc", sel+1); if ((theApp.GetLocalizedString(sname, s, sizeof(s))) && (s[0])) pszDesc = s; } Modified: trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp =================================================================== --- trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/mptrack/PatternEditorDialogs.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -1505,14 +1505,14 @@ m_CbnSplitNote.SetCurSel(m_Settings.splitNote - (m_pSndFile->GetModSpecifications().noteMin - NOTE_MIN)); // Octave modifier - for(int i = -SPLIT_OCTAVE_RANGE; i < SPLIT_OCTAVE_RANGE + 1; i++) + for(int i = -SplitKeyboardSettings::splitOctaveRange; i < SplitKeyboardSettings::splitOctaveRange + 1; i++) { wsprintf(s, i < 0 ? "Octave -%d" : i > 0 ? "Octave +%d" : "No Change", abs(i)); int n = m_CbnOctaveModifier.AddString(s); m_CbnOctaveModifier.SetItemData(n, i); } - m_CbnOctaveModifier.SetCurSel(m_Settings.octaveModifier + SPLIT_OCTAVE_RANGE); + m_CbnOctaveModifier.SetCurSel(m_Settings.octaveModifier + SplitKeyboardSettings::splitOctaveRange); CheckDlgButton(IDC_PATTERN_OCTAVELINK, (m_Settings.octaveLink && m_Settings.octaveModifier != 0) ? MF_CHECKED : MF_UNCHECKED); // Volume @@ -1565,7 +1565,7 @@ CDialog::OnOK(); m_Settings.splitNote = static_cast<ModCommand::NOTE>(m_CbnSplitNote.GetCurSel() + (m_pSndFile->GetModSpecifications().noteMin - NOTE_MIN)); - m_Settings.octaveModifier = m_CbnOctaveModifier.GetCurSel() - SPLIT_OCTAVE_RANGE; + m_Settings.octaveModifier = m_CbnOctaveModifier.GetCurSel() - SplitKeyboardSettings::splitOctaveRange; m_Settings.octaveLink = (IsDlgButtonChecked(IDC_PATTERN_OCTAVELINK) == TRUE); m_Settings.splitVolume = static_cast<ModCommand::VOL>(m_CbnSplitVolume.GetCurSel()); m_Settings.splitInstrument = static_cast<ModCommand::INSTR>(m_CbnSplitInstrument.GetItemData(m_CbnSplitInstrument.GetCurSel())); Modified: trunk/OpenMPT/soundlib/Load_s3m.cpp =================================================================== --- trunk/OpenMPT/soundlib/Load_s3m.cpp 2012-04-23 15:28:34 UTC (rev 1254) +++ trunk/OpenMPT/soundlib/Load_s3m.cpp 2012-04-27 20:05:26 UTC (rev 1255) @@ -114,22 +114,16 @@ } else command = 0; break; case CMD_MODCMDEX: - command = 'S'; - switch(param & 0xF0) { - case 0x00: command = 0; break; - case 0x10: command = 'F'; param |= 0xF0; break; - case 0x20: command = 'E'; param |= 0xF0; break; - case 0x30: param = (param & 0x0F) | 0x10; break; - case 0x40: param = (param & 0x0F) | 0x30; break; - case 0x50: param = (param & 0x0F) | 0x20; break; - case 0x60: param = (param & 0x0F) | 0xB0; break; - case 0x70: param = (param & 0x0F) | 0x40; break; - case 0x90: command = 'Q'; param &= 0x0F; break; - case 0xA0: if(param & 0x0F) { command = 'D'; param = (param << 4) | 0x0F; } else command = 0; break; - case 0xB0: if(param & 0x0F) { command = 'D'; param |= 0xF0; } else command = 0; break; + ModCommand m; + m.command = CMD_MODCMDEX; + m.param = param; + m.ExtendedMODtoS3MEffect(); + command = m.command; + param = m.param; + S3MSaveConvert(command, param, toIT, compatibilityExport); } - break; + return; // Chars under 0x40 don't save properly, so map : to ] and # to [. case CMD_DELAYCUT: if(compatibilityExport || !toIT) @@ -279,7 +273,7 @@ uint32 c5speed; // Middle-C frequency char reserved2[12]; // Reserved + Internal ST3 stuff char name[28]; // Sample name - uint32 magic; // "SCRS" magic bytes + uint32 magic; // "SCRS" magic bytes ("SCRI" for Adlib instruments) // Convert all multi-byte numeric values to current platform's endianness or vice versa. void ConvertEndianness() @@ -518,11 +512,11 @@ } else { m_nChannels = i + 1; - ChnSettings[i].nPan = (fileHeader.channels[i] & 8) ? 192 : 64; + ChnSettings[i].nPan = (fileHeader.channels[i] & 8) ? 192 : 64; // 200 : 56 if(fileHeader.channels[i] & 0x80) { ChnSettings[i].dwFlags = CHN_MUTE; - // Detect Adlib channels here: + // Detect Adlib channels here (except for OpenMPT 1.19 and older, which would write wrong channel types for PCM channels 16-32): // c = channels[i] ^ 0x80; // if(c >= 16 && c < 32) adlibChannel = true; } @@ -799,7 +793,7 @@ // Version info following: ST3.20 = 0x1320 // Most significant nibble = Tracker ID, see S3MFileHeader::S3MTrackerVersions // Following: One nibble = Major version, one byte = Minor version (hex) - fileHeader.cwtv = S3MFileHeader::trackerMask | static_cast<uint16>((MptVersion::num >> 16) & S3MFileHeader::versionMask); + fileHeader.cwtv = S3MFileHeader::trkOpenMPT | static_cast<uint16>((MptVersion::num >> 16) & S3MFileHeader::versionMask); fileHeader.formatVersion = S3MFileHeader::newVersion; fileHeader.magic = S3MFileHeader::idSCRM; @@ -816,8 +810,9 @@ { if(chn < GetNumChannels()) { - uint8 ch = (chn & 0x0F) >> 1; - ch = (chn & 0x10) | ((chn & 1) ? 8 + ch : ch); + // ST3 only supports 16 PCM channels, so if channels 17-32 are used, + // they must be mapped to the same "internal channels" as channels 1-16. + uint8 ch = ((chn << 3) | (chn >> 1)) & 0x0F; if((ChnSettings[chn].dwFlags & CHN_MUTE) != 0) { ch |= 0x80; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |