You can subscribe to this list here.
| 2006 |
Jan
|
Feb
|
Mar
(1) |
Apr
(1) |
May
|
Jun
(1) |
Jul
|
Aug
(10) |
Sep
|
Oct
|
Nov
|
Dec
(3) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2007 |
Jan
(1) |
Feb
(2) |
Mar
(3) |
Apr
(2) |
May
(10) |
Jun
(2) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
|
| 2008 |
Jan
(6) |
Feb
(4) |
Mar
(5) |
Apr
(2) |
May
(1) |
Jun
(1) |
Jul
(4) |
Aug
(6) |
Sep
(2) |
Oct
(9) |
Nov
(1) |
Dec
(4) |
| 2009 |
Jan
(9) |
Feb
(2) |
Mar
(2) |
Apr
(2) |
May
(6) |
Jun
(18) |
Jul
(33) |
Aug
(39) |
Sep
(33) |
Oct
(24) |
Nov
(23) |
Dec
(22) |
| 2010 |
Jan
(29) |
Feb
(32) |
Mar
(51) |
Apr
(17) |
May
(31) |
Jun
(21) |
Jul
(32) |
Aug
(28) |
Sep
(35) |
Oct
(27) |
Nov
(11) |
Dec
(13) |
| 2011 |
Jan
(14) |
Feb
(13) |
Mar
(27) |
Apr
(27) |
May
(28) |
Jun
(20) |
Jul
(43) |
Aug
(52) |
Sep
(66) |
Oct
(61) |
Nov
(11) |
Dec
(8) |
| 2012 |
Jan
(20) |
Feb
(30) |
Mar
(38) |
Apr
(21) |
May
(33) |
Jun
(21) |
Jul
(25) |
Aug
(9) |
Sep
(24) |
Oct
(42) |
Nov
(27) |
Dec
(41) |
| 2013 |
Jan
(20) |
Feb
(35) |
Mar
(156) |
Apr
(298) |
May
(258) |
Jun
(201) |
Jul
(105) |
Aug
(60) |
Sep
(193) |
Oct
(245) |
Nov
(280) |
Dec
(194) |
| 2014 |
Jan
(63) |
Feb
(202) |
Mar
(200) |
Apr
(23) |
May
(53) |
Jun
(105) |
Jul
(18) |
Aug
(26) |
Sep
(110) |
Oct
(187) |
Nov
(97) |
Dec
(74) |
| 2015 |
Jan
(45) |
Feb
(55) |
Mar
(116) |
Apr
(116) |
May
(193) |
Jun
(164) |
Jul
(50) |
Aug
(111) |
Sep
(98) |
Oct
(71) |
Nov
(103) |
Dec
(63) |
| 2016 |
Jan
(33) |
Feb
(101) |
Mar
(182) |
Apr
(139) |
May
(140) |
Jun
(103) |
Jul
(165) |
Aug
(286) |
Sep
(208) |
Oct
(127) |
Nov
(97) |
Dec
(54) |
| 2017 |
Jan
(64) |
Feb
(335) |
Mar
(202) |
Apr
(212) |
May
(139) |
Jun
(127) |
Jul
(294) |
Aug
(154) |
Sep
(170) |
Oct
(152) |
Nov
(156) |
Dec
(62) |
| 2018 |
Jan
(168) |
Feb
(237) |
Mar
(196) |
Apr
(174) |
May
(174) |
Jun
(161) |
Jul
(127) |
Aug
(88) |
Sep
(149) |
Oct
(66) |
Nov
(52) |
Dec
(135) |
| 2019 |
Jan
(146) |
Feb
(126) |
Mar
(104) |
Apr
(58) |
May
(60) |
Jun
(28) |
Jul
(197) |
Aug
(129) |
Sep
(141) |
Oct
(148) |
Nov
(63) |
Dec
(100) |
| 2020 |
Jan
(74) |
Feb
(37) |
Mar
(59) |
Apr
(154) |
May
(194) |
Jun
(133) |
Jul
(313) |
Aug
(197) |
Sep
(49) |
Oct
(162) |
Nov
(143) |
Dec
(57) |
| 2021 |
Jan
(120) |
Feb
(107) |
Mar
(314) |
Apr
(157) |
May
(524) |
Jun
(169) |
Jul
(72) |
Aug
(133) |
Sep
(135) |
Oct
(146) |
Nov
(198) |
Dec
(325) |
| 2022 |
Jan
(409) |
Feb
(249) |
Mar
(138) |
Apr
(95) |
May
(102) |
Jun
(221) |
Jul
(66) |
Aug
(120) |
Sep
(192) |
Oct
(131) |
Nov
(53) |
Dec
(171) |
| 2023 |
Jan
(357) |
Feb
(82) |
Mar
(168) |
Apr
(218) |
May
(196) |
Jun
(86) |
Jul
(115) |
Aug
(49) |
Sep
(190) |
Oct
(102) |
Nov
(45) |
Dec
(76) |
| 2024 |
Jan
(86) |
Feb
(50) |
Mar
(324) |
Apr
(209) |
May
(197) |
Jun
(232) |
Jul
(194) |
Aug
(247) |
Sep
(219) |
Oct
(266) |
Nov
(328) |
Dec
(304) |
| 2025 |
Jan
(191) |
Feb
(115) |
Mar
(137) |
Apr
(32) |
May
(126) |
Jun
(403) |
Jul
(213) |
Aug
(184) |
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <sv...@op...> - 2024-05-28 16:40:21
|
Author: sagamusix Date: Mon May 27 21:34:41 2024 New Revision: 20863 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20863 Log: [Fix] IT compatibility: Offset with instrument number but no note plays offset effect with previous note (https://bugs.openmpt.org/view.php?id=1785). Modified: trunk/OpenMPT/common/versionNumber.h trunk/OpenMPT/mptrack/dlg_misc.cpp trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Snd_fx.cpp trunk/OpenMPT/soundlib/Sndfile.cpp trunk/OpenMPT/soundlib/UpgradeModule.cpp Modified: trunk/OpenMPT/common/versionNumber.h ============================================================================== --- trunk/OpenMPT/common/versionNumber.h Sun May 26 22:50:38 2024 (r20862) +++ trunk/OpenMPT/common/versionNumber.h Mon May 27 21:34:41 2024 (r20863) @@ -18,6 +18,6 @@ #define VER_MAJORMAJOR 1 #define VER_MAJOR 32 #define VER_MINOR 00 -#define VER_MINORMINOR 14 +#define VER_MINORMINOR 15 OPENMPT_NAMESPACE_END Modified: trunk/OpenMPT/mptrack/dlg_misc.cpp ============================================================================== --- trunk/OpenMPT/mptrack/dlg_misc.cpp Sun May 26 22:50:38 2024 (r20862) +++ trunk/OpenMPT/mptrack/dlg_misc.cpp Mon May 27 21:34:41 2024 (r20863) @@ -711,6 +711,7 @@ case kPluginDefaultProgramAndBank1: desc = _T("Assume initial plugin MIDI program and bank number is 1"); break; case kITNoSustainOnPortamento: desc = _T("Portamento after note-off does not re-enable sample sustain loop"); break; case kITEmptyNoteMapSlotIgnoreCell: desc = _T("Ignore pattern cell completely when trying to play unmapped instrument note"); break; + case kITOffsetWithInstrNumber: desc = _T("Offset command with instrument number recalls offset with last note"); break; default: MPT_ASSERT_NOTREACHED(); } Modified: trunk/OpenMPT/soundlib/Snd_defs.h ============================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h Sun May 26 22:50:38 2024 (r20862) +++ trunk/OpenMPT/soundlib/Snd_defs.h Mon May 27 21:34:41 2024 (r20863) @@ -590,6 +590,7 @@ kPluginDefaultProgramAndBank1, // Default program and bank is set to 1 for plugins, so if an instrument is set to either of those, the program / bank change event is not sent to the plugin kITNoSustainOnPortamento, // Do not re-enable sustain loop on portamento, even when switching between samples kITEmptyNoteMapSlotIgnoreCell, // IT ignores the entire pattern cell when trying to play an unmapped note of an instrument + kITOffsetWithInstrNumber, // IT applies offset commands even if just an instrument number without note is present // Add new play behaviours here. Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp Sun May 26 22:50:38 2024 (r20862) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp Mon May 27 21:34:41 2024 (r20863) @@ -5683,13 +5683,14 @@ param /= 2u; } - if(chn.rowCommand.IsNote() || m_playBehaviour[kApplyOffsetWithoutNote]) + const auto note = (m_playBehaviour[kITOffsetWithInstrNumber] && chn.rowCommand.instr) ? chn.nNewNote : chn.rowCommand.note; + if(ModCommand::IsNote(note) || m_playBehaviour[kApplyOffsetWithoutNote]) { // IT compatibility: If this note is not mapped to a sample, ignore it. // Test case: empty_sample_offset.it - if(chn.pModInstrument != nullptr && chn.rowCommand.IsNote()) + if(chn.pModInstrument != nullptr && ModCommand::IsNote(note)) { - SAMPLEINDEX smp = chn.pModInstrument->Keyboard[chn.rowCommand.note - NOTE_MIN]; + SAMPLEINDEX smp = chn.pModInstrument->Keyboard[note - NOTE_MIN]; if(smp == 0 || smp > GetNumSamples()) return; } Modified: trunk/OpenMPT/soundlib/Sndfile.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Sndfile.cpp Sun May 26 22:50:38 2024 (r20862) +++ trunk/OpenMPT/soundlib/Sndfile.cpp Mon May 27 21:34:41 2024 (r20863) @@ -1184,6 +1184,7 @@ playBehaviour.set(kITInitialNoteMemory); playBehaviour.set(kITNoSustainOnPortamento); playBehaviour.set(kITEmptyNoteMapSlotIgnoreCell); + playBehaviour.set(kITOffsetWithInstrNumber); break; case MOD_TYPE_XM: Modified: trunk/OpenMPT/soundlib/UpgradeModule.cpp ============================================================================== --- trunk/OpenMPT/soundlib/UpgradeModule.cpp Sun May 26 22:50:38 2024 (r20862) +++ trunk/OpenMPT/soundlib/UpgradeModule.cpp Mon May 27 21:34:41 2024 (r20863) @@ -598,6 +598,7 @@ { kITInitialNoteMemory, MPT_V("1.31.00.25") }, { kITNoSustainOnPortamento, MPT_V("1.32.00.13") }, { kITEmptyNoteMapSlotIgnoreCell, MPT_V("1.32.00.13") }, + { kITOffsetWithInstrNumber, MPT_V("1.32.00.15") }, }; for(const auto &b : behaviours) |
|
From: <sv...@op...> - 2024-05-28 16:30:24
|
Author: sagamusix Date: Sun May 26 18:31:11 2024 New Revision: 20854 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20854 Log: [Fix] MDL: Slide depth broke when introducing Hertz instead of periods in non-linear mode. Modified: trunk/OpenMPT/soundlib/Load_dtm.cpp trunk/OpenMPT/soundlib/Load_mdl.cpp trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/soundlib/Load_dtm.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_dtm.cpp Sun May 26 00:52:48 2024 (r20853) +++ trunk/OpenMPT/soundlib/Load_dtm.cpp Sun May 26 18:31:11 2024 (r20854) @@ -231,6 +231,7 @@ InitializeGlobals(MOD_TYPE_DTM); InitializeChannels(); m_SongFlags.set(SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS | SONG_FASTPORTAS); + m_playBehaviour.reset(kPeriodsAreHertz); m_playBehaviour.reset(kITVibratoTremoloPanbrello); // Various files have a default speed or tempo of 0 if(fileHeader.tempo) Modified: trunk/OpenMPT/soundlib/Load_mdl.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_mdl.cpp Sun May 26 00:52:48 2024 (r20853) +++ trunk/OpenMPT/soundlib/Load_mdl.cpp Sun May 26 18:31:11 2024 (r20854) @@ -477,6 +477,7 @@ m_SongFlags = SONG_ITCOMPATGXX; m_playBehaviour.set(kPerChannelGlobalVolSlide); m_playBehaviour.set(kApplyOffsetWithoutNote); + m_playBehaviour.reset(kPeriodsAreHertz); m_playBehaviour.reset(kITVibratoTremoloPanbrello); m_playBehaviour.reset(kITSCxStopsSample); // Gate effect in underbeat.mdl Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp Sun May 26 00:52:48 2024 (r20853) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp Sun May 26 18:31:11 2024 (r20854) @@ -6395,6 +6395,7 @@ if(GetType() & (MOD_TYPE_MDL | MOD_TYPE_DTM)) { // MDL uses non-linear slides, but their effectiveness does not depend on the middle-C frequency. + MPT_ASSERT(!PeriodsAreFrequencies()); return (FreqS3MTable[note % 12u] << 4) >> (note / 12); } if(!nC5Speed) @@ -6513,6 +6514,7 @@ return (period + c5speed - 8363) << FREQ_FRACBITS; } else if(GetType() & (MOD_TYPE_MDL | MOD_TYPE_DTM)) { + MPT_ASSERT(!PeriodsAreFrequencies()); LimitMax(period, Util::MaxValueOfType(period) >> 8); if (!c5speed) c5speed = 8363; return Util::muldiv_unsigned(c5speed, (1712L << 7) << FREQ_FRACBITS, (period << 8) + nPeriodFrac); |
|
From: <sv...@op...> - 2024-05-28 16:30:18
|
Author: sagamusix Date: Sun May 26 22:35:07 2024 New Revision: 20855 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20855 Log: Merged revision(s) 20846-20848, 20854 from trunk/OpenMPT: [Mod] MED: Don't seek to and read pattern name position if the length is 0 anyway. ........ [Fix] STP: Volume slide nibbles are not just swapped, but they are always both executed (so up and down are added together). [Ref] Cleanup STP loader. ........ [Fix] S3M: Don't update effect memory from cells without a command. This could happen after editing a pattern. ........ [Fix] MDL: Slide depth broke when introducing Hertz instead of periods in non-linear mode. ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/soundlib/Load_dtm.cpp branches/OpenMPT-1.31/soundlib/Load_mdl.cpp branches/OpenMPT-1.31/soundlib/Load_med.cpp branches/OpenMPT-1.31/soundlib/Load_stp.cpp branches/OpenMPT-1.31/soundlib/Snd_fx.cpp Modified: branches/OpenMPT-1.31/soundlib/Load_dtm.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_dtm.cpp Sun May 26 18:31:11 2024 (r20854) +++ branches/OpenMPT-1.31/soundlib/Load_dtm.cpp Sun May 26 22:35:07 2024 (r20855) @@ -231,6 +231,7 @@ InitializeGlobals(MOD_TYPE_DTM); InitializeChannels(); m_SongFlags.set(SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS); + m_playBehaviour.reset(kPeriodsAreHertz); m_playBehaviour.reset(kITVibratoTremoloPanbrello); // Various files have a default speed or tempo of 0 if(fileHeader.tempo) Modified: branches/OpenMPT-1.31/soundlib/Load_mdl.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_mdl.cpp Sun May 26 18:31:11 2024 (r20854) +++ branches/OpenMPT-1.31/soundlib/Load_mdl.cpp Sun May 26 22:35:07 2024 (r20855) @@ -478,6 +478,7 @@ m_SongFlags = SONG_ITCOMPATGXX; m_playBehaviour.set(kPerChannelGlobalVolSlide); m_playBehaviour.set(kApplyOffsetWithoutNote); + m_playBehaviour.reset(kPeriodsAreHertz); m_playBehaviour.reset(kITVibratoTremoloPanbrello); m_playBehaviour.reset(kITSCxStopsSample); // Gate effect in underbeat.mdl Modified: branches/OpenMPT-1.31/soundlib/Load_med.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_med.cpp Sun May 26 18:31:11 2024 (r20854) +++ branches/OpenMPT-1.31/soundlib/Load_med.cpp Sun May 26 22:35:07 2024 (r20855) @@ -101,7 +101,7 @@ { FLAG_FILTERON = 0x01, // The hardware audio filter is on FLAG_JUMPINGON = 0x02, // Mouse pointer jumping on - FLAG_JUMP8TH = 0x04, // ump every 8th line (not in OctaMED Pro) + FLAG_JUMP8TH = 0x04, // Jump every 8th line (not in OctaMED Pro) FLAG_INSTRSATT = 0x08, // sng+samples indicator (not useful in MMDs) FLAG_VOLHEX = 0x10, // volumes are HEX FLAG_STSLIDE = 0x20, // use ST/NT/PT compatible sliding @@ -484,7 +484,7 @@ } break; case 0x10: // MIDI message - m.SetEffectCommand(CMD_MIDI, param | 0x80); + m.SetEffectCommand(CMD_MIDI, 0x80 | param); break; case 0x11: // Slide pitch up m.SetEffectCommand(CMD_MODCMDEX, 0x10 | nibbleLo); @@ -1374,7 +1374,9 @@ file.Seek(patHeader.blockInfoOffset); MMDBlockInfo blockInfo; file.ReadStruct(blockInfo); - if(file.Seek(blockInfo.nameOffset)) + if(blockInfo.nameLength + && blockInfo.nameOffset + && file.Seek(blockInfo.nameOffset)) { // We have now chased four pointers to get this far... lovely format. file.ReadString<mpt::String::maybeNullTerminated>(patName, blockInfo.nameLength); Modified: branches/OpenMPT-1.31/soundlib/Load_stp.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_stp.cpp Sun May 26 18:31:11 2024 (r20854) +++ branches/OpenMPT-1.31/soundlib/Load_stp.cpp Sun May 26 22:35:07 2024 (r20855) @@ -441,18 +441,16 @@ const auto [instr, note, command, param] = file.ReadArray<uint8, 4>(); m.instr = instr; - m.note = note; m.param = param; - - if(m.note) + if(note) { - m.note += 24 + NOTE_MIN; + m.note = NOTE_MIDDLEC - 36 + note; chnMem = ChannelMemory(); } - // this is a nibble-swapped param value used for auto fine volside - // and auto global fine volside - uint8 swapped = (m.param >> 4) | (m.param << 4); + // Volume slides not only have their nibbles swapped, but the up and down parameters also add up + const int totalSlide = -static_cast<int>(m.param >> 4) + (m.param & 0x0F); + const uint8 slideParam = static_cast<uint8>((totalSlide > 0) ? totalSlide << 4 : -totalSlide); if((command & 0xF0) == 0xF0) { @@ -462,138 +460,93 @@ { m.param = mpt::saturate_round<ModCommand::PARAM>(ConvertTempo(ciaTempo).ToDouble()); m.command = CMD_TEMPO; - } else - { - m.command = CMD_NONE; } } else switch(command) { case 0x00: // arpeggio if(m.param) m.command = CMD_ARPEGGIO; - else - m.command = CMD_NONE; break; - case 0x01: // portamento up m.command = CMD_PORTAMENTOUP; break; - case 0x02: // portamento down m.command = CMD_PORTAMENTODOWN; break; - case 0x03: // auto fine portamento up chnMem.autoFinePorta = 0x10 | std::min(m.param, ModCommand::PARAM(15)); chnMem.autoPortaUp = 0; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x04: // auto fine portamento down chnMem.autoFinePorta = 0x20 | std::min(m.param, ModCommand::PARAM(15)); chnMem.autoPortaUp = 0; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x05: // auto portamento up chnMem.autoFinePorta = 0; chnMem.autoPortaUp = m.param; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x06: // auto portamento down chnMem.autoFinePorta = 0; chnMem.autoPortaUp = 0; chnMem.autoPortaDown = m.param; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x07: // set global volume m.command = CMD_GLOBALVOLUME; globalVolSlide = 0; break; - case 0x08: // auto global fine volume slide - globalVolSlide = swapped; - m.command = CMD_NONE; + globalVolSlide = slideParam; break; - case 0x09: // fine portamento up m.command = CMD_MODCMDEX; m.param = 0x10 | std::min(m.param, ModCommand::PARAM(15)); break; - case 0x0A: // fine portamento down m.command = CMD_MODCMDEX; m.param = 0x20 | std::min(m.param, ModCommand::PARAM(15)); break; - case 0x0B: // auto fine volume slide - chnMem.autoVolSlide = swapped; - m.command = CMD_NONE; + chnMem.autoVolSlide = slideParam; break; - case 0x0C: // set volume m.volcmd = VOLCMD_VOLUME; m.vol = m.param; chnMem.autoVolSlide = 0; - m.command = CMD_NONE; break; - case 0x0D: // volume slide (param is swapped compared to .mod) - if(m.param & 0xF0) - { - m.volcmd = VOLCMD_VOLSLIDEDOWN; - m.vol = m.param >> 4; - } else if(m.param & 0x0F) - { - m.volcmd = VOLCMD_VOLSLIDEUP; - m.vol = m.param & 0xF; - } + if(totalSlide < 0) + m.SetVolumeCommand(VOLCMD_VOLSLIDEDOWN, slideParam & 0x0F); + else if(totalSlide > 0) + m.SetVolumeCommand(VOLCMD_VOLSLIDEUP, slideParam >> 4); chnMem.autoVolSlide = 0; - m.command = CMD_NONE; break; - case 0x0E: // set filter (also uses opposite value compared to .mod) - m.command = CMD_MODCMDEX; - m.param = 1 ^ (m.param ? 1 : 0); + m.SetEffectCommand(CMD_MODCMDEX, 1 ^ (m.param ? 1 : 0)); break; - case 0x0F: // set speed - m.command = CMD_SPEED; speedFrac = m.param & 0x0F; - m.param >>= 4; + m.SetEffectCommand(CMD_SPEED, m.param >> 4); break; - case 0x10: // auto vibrato chnMem.autoVibrato = m.param; chnMem.vibratoMem = 0; - m.command = CMD_NONE; break; - case 0x11: // auto tremolo if(m.param & 0xF) chnMem.autoTremolo = m.param; else chnMem.autoTremolo = 0; - m.command = CMD_NONE; break; - case 0x12: // pattern break m.command = CMD_PATTERNBREAK; break; - case 0x13: // auto tone portamento chnMem.autoFinePorta = 0; chnMem.autoPortaUp = 0; @@ -601,13 +554,10 @@ chnMem.autoTonePorta = m.param; chnMem.tonePortaMem = 0; - m.command = CMD_NONE; break; - case 0x14: // position jump m.command = CMD_POSITIONJUMP; break; - case 0x16: // start loop sequence if(m.instr && m.instr <= loopInfo.size()) { @@ -620,10 +570,7 @@ m.vol = m.param; } } - - m.command = CMD_NONE; break; - case 0x17: // play only loop nn if(m.instr && m.instr <= loopInfo.size()) { @@ -637,10 +584,7 @@ m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].looped); } } - - m.command = CMD_NONE; break; - case 0x18: // play sequence without loop if(m.instr && m.instr <= loopInfo.size()) { @@ -657,10 +601,7 @@ nonLooped[m.instr - 1] = ++m_nSamples; m.instr = static_cast<ModCommand::INSTR>(nonLooped[m.instr - 1]); } - - m.command = CMD_NONE; break; - case 0x19: // play only loop nn without loop if(m.instr && m.instr <= loopInfo.size()) { @@ -674,54 +615,37 @@ m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].nonLooped); } } - - m.command = CMD_NONE; break; - case 0x1D: // fine volume slide (nibble order also swapped) - m.command = CMD_VOLUMESLIDE; - m.param = swapped; - if(m.param & 0xF0) // slide down - m.param |= 0x0F; - else if(m.param & 0x0F) - m.param |= 0xF0; + if(totalSlide < 0) // slide down + m.SetEffectCommand(CMD_MODCMDEX, 0xB0 | (slideParam & 0x0F)); + else if(totalSlide > 0) + m.SetEffectCommand(CMD_MODCMDEX, 0xA0 | (slideParam >> 4)); break; - case 0x20: // "delayed fade" // just behave like either a normal fade or a notecut // depending on the speed if(m.param & 0xF0) { chnMem.autoVolSlide = m.param >> 4; - m.command = CMD_NONE; } else { - m.command = CMD_MODCMDEX; - m.param = 0xC0 | (m.param & 0xF); + m.SetEffectCommand(CMD_MODCMDEX, 0xC0 | (m.param & 0xF)); } break; - case 0x21: // note delay - m.command = CMD_MODCMDEX; - m.param = 0xD0 | std::min(m.param, ModCommand::PARAM(15)); + m.SetEffectCommand(CMD_MODCMDEX, 0xD0 | std::min(m.param, ModCommand::PARAM(15))); break; - case 0x22: // retrigger note - m.command = CMD_MODCMDEX; - m.param = 0x90 | std::min(m.param, ModCommand::PARAM(15)); + m.SetEffectCommand(CMD_MODCMDEX, 0x90 | std::min(m.param, ModCommand::PARAM(15))); break; - case 0x49: // set sample offset m.command = CMD_OFFSET; break; - case 0x4E: // other protracker commands (pattern loop / delay) if((m.param & 0xF0) == 0x60 || (m.param & 0xF0) == 0xE0) m.command = CMD_MODCMDEX; - else - m.command = CMD_NONE; break; - case 0x4F: // set speed/tempo if(m.param < 0x20) { @@ -732,9 +656,7 @@ m.command = CMD_TEMPO; } break; - default: - m.command = CMD_NONE; break; } Modified: branches/OpenMPT-1.31/soundlib/Snd_fx.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Snd_fx.cpp Sun May 26 18:31:11 2024 (r20854) +++ branches/OpenMPT-1.31/soundlib/Snd_fx.cpp Sun May 26 22:35:07 2024 (r20855) @@ -979,7 +979,7 @@ break; } - if(m_playBehaviour[kST3EffectMemory] && param != 0) + if(m_playBehaviour[kST3EffectMemory] && command != CMD_NONE && param != 0) { UpdateS3MEffectMemory(chn, param); } @@ -3553,7 +3553,7 @@ break; } - if(m_playBehaviour[kST3EffectMemory] && param != 0) + if(m_playBehaviour[kST3EffectMemory] && cmd != CMD_NONE && param != 0) { UpdateS3MEffectMemory(chn, static_cast<ModCommand::PARAM>(param)); } @@ -6155,6 +6155,7 @@ if(GetType() & (MOD_TYPE_MDL | MOD_TYPE_DTM)) { // MDL uses non-linear slides, but their effectiveness does not depend on the middle-C frequency. + MPT_ASSERT(!PeriodsAreFrequencies()); return (FreqS3MTable[note % 12u] << 4) >> (note / 12); } if(!nC5Speed) @@ -6273,6 +6274,7 @@ return (period + c5speed - 8363) << FREQ_FRACBITS; } else if(GetType() & (MOD_TYPE_MDL | MOD_TYPE_DTM)) { + MPT_ASSERT(!PeriodsAreFrequencies()); LimitMax(period, Util::MaxValueOfType(period) >> 8); if (!c5speed) c5speed = 8363; return Util::muldiv_unsigned(c5speed, (1712L << 7) << FREQ_FRACBITS, (period << 8) + nPeriodFrac); |
|
From: <sv...@op...> - 2024-05-28 16:26:23
|
Author: sagamusix Date: Tue May 28 18:26:15 2024 New Revision: 20865 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20865 Log: [Imp] IT: Disable offset-without-note quirk for older SchismTracker versions. Modified: trunk/OpenMPT/soundlib/Load_it.cpp Modified: trunk/OpenMPT/soundlib/Load_it.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_it.cpp Mon May 27 21:36:15 2024 (r20864) +++ trunk/OpenMPT/soundlib/Load_it.cpp Tue May 28 18:26:15 2024 (r20865) @@ -1304,6 +1304,9 @@ // Empty instrument sample map slot ignores complete pattern cell: Added 2024-05-12, https://github.com/schismtracker/schismtracker/commit/aa84148e019a65f3d52ecd33fd84bfecfdb87bf4 m_playBehaviour.reset(kITEmptyNoteMapSlotIgnoreCell); } + // Offset without note: Added 2024-05-27, https://github.com/schismtracker/schismtracker/commit/9237960d45079a54ad73f87bacfe5dd8ae82e273 + if(schismDateVersion < SchismVersionFromDate<2024, 05, 27>::date) + m_playBehaviour.reset(kITOffsetWithInstrNumber); break; case 4: madeWithTracker = MPT_UFORMAT("pyIT {}.{}")((fileHeader.cwtv & 0x0F00) >> 8, mpt::ufmt::hex0<2>(fileHeader.cwtv & 0xFF)); |
|
From: <sv...@op...> - 2024-05-28 16:20:18
|
Author: sagamusix Date: Sun May 26 00:52:48 2024 New Revision: 20853 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20853 Log: [Imp] Further fixes for formats where auto tone portamento is not reset by parameter 0. Modified: trunk/OpenMPT/soundlib/Load_far.cpp trunk/OpenMPT/soundlib/Load_ult.cpp trunk/OpenMPT/soundlib/Load_xmf.cpp trunk/OpenMPT/soundlib/Snd_defs.h trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/soundlib/Load_far.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_far.cpp Sun May 26 00:37:33 2024 (r20852) +++ trunk/OpenMPT/soundlib/Load_far.cpp Sun May 26 00:52:48 2024 (r20853) @@ -168,7 +168,7 @@ Order().SetDefaultSpeed(fileHeader.defaultSpeed); Order().SetDefaultTempoInt(80); m_nDefaultGlobalVolume = MAX_GLOBAL_VOLUME; - m_SongFlags = SONG_LINEARSLIDES | SONG_AUTO_TONEPORTA; + m_SongFlags = SONG_LINEARSLIDES | SONG_AUTO_TONEPORTA | SONG_AUTO_TONEPORTA_CONT; m_playBehaviour.set(kPeriodsAreHertz); m_modFormat.formatName = U_("Farandole Composer"); Modified: trunk/OpenMPT/soundlib/Load_ult.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_ult.cpp Sun May 26 00:37:33 2024 (r20852) +++ trunk/OpenMPT/soundlib/Load_ult.cpp Sun May 26 00:52:48 2024 (r20853) @@ -312,8 +312,10 @@ m_modFormat.madeWithTracker = U_("UltraTracker ") + versions[fileHeader.version - '1']; m_modFormat.charset = mpt::Charset::CP437; - m_SongFlags = SONG_AUTO_TONEPORTA | SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS; // this will be converted to IT format by MPT. + m_SongFlags = SONG_AUTO_TONEPORTA | SONG_AUTO_TONEPORTA_CONT | SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS; // this will be converted to IT format by MPT. m_playBehaviour.reset(kITClearPortaTarget); + m_playBehaviour.reset(kITPortaTargetReached); + m_playBehaviour.set(kFT2PortaTargetNoReset); // Read "messageLength" lines, each containing 32 characters. m_songMessage.ReadFixedLineLength(file, fileHeader.messageLength * 32, 32, 0); Modified: trunk/OpenMPT/soundlib/Load_xmf.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_xmf.cpp Sun May 26 00:37:33 2024 (r20852) +++ trunk/OpenMPT/soundlib/Load_xmf.cpp Sun May 26 00:52:48 2024 (r20853) @@ -166,7 +166,7 @@ InitializeGlobals(MOD_TYPE_MOD); m_SongFlags.set(SONG_IMPORTED); m_SongFlags.reset(SONG_ISAMIGA); - m_SongFlags.set(SONG_AUTO_TONEPORTA, type < 4); + m_SongFlags.set(SONG_AUTO_TONEPORTA | SONG_AUTO_TONEPORTA_CONT, type < 4); m_nSamples = numSamples; m_nSamplePreAmp = (type == 3) ? 192 : 48; // Imperium Galactica files are really quiet, no other XMFs appear to use type 3 Modified: trunk/OpenMPT/soundlib/Snd_defs.h ============================================================================== --- trunk/OpenMPT/soundlib/Snd_defs.h Sun May 26 00:37:33 2024 (r20852) +++ trunk/OpenMPT/soundlib/Snd_defs.h Sun May 26 00:52:48 2024 (r20853) @@ -279,23 +279,24 @@ // Module flags - contains both song configuration and playback state... Use SONG_FILE_FLAGS and SONG_PLAY_FLAGS distinguish between the two. enum SongFlags { - SONG_FASTPORTAS = 0x01, // Portamentos are executed on every tick - SONG_FASTVOLSLIDES = 0x02, // Old Scream Tracker 3.0 volume slides (executed on every tick) - SONG_ITOLDEFFECTS = 0x04, // Old Impulse Tracker effect implementations - SONG_ITCOMPATGXX = 0x08, // IT "Compatible Gxx" (IT's flag to behave more like other trackers w/r/t portamento effects) - SONG_LINEARSLIDES = 0x10, // Linear slides vs. Amiga slides - SONG_EXFILTERRANGE = 0x20, // Cutoff Filter has double frequency range (up to ~10Khz) - SONG_AMIGALIMITS = 0x40, // Enforce amiga frequency limits - SONG_S3MOLDVIBRATO = 0x80, // ScreamTracker 2 vibrato in S3M files - SONG_PT_MODE = 0x100, // ProTracker 1/2 playback mode - SONG_ISAMIGA = 0x200, // Is an Amiga module and thus qualifies to be played using the Paula BLEP resampler - SONG_IMPORTED = 0x400, // Song type does not represent actual module format / was imported from a different format (OpenMPT) - SONG_PLAYALLSONGS = 0x800, // Play all subsongs consecutively (libopenmpt) - SONG_AUTO_TONEPORTA = 0x1000, // Tone portamento command is continued automatically - SONG_AUTO_GLOBALVOL = 0x2000, // Global volume slide command is continued automatically - SONG_AUTO_VIBRATO = 0x4000, // Vibrato command is continued automatically - SONG_AUTO_TREMOLO = 0x8000, // Tremolo command is continued automatically - SONG_AUTO_VOLSLIDE_STK = 0x1'0000, // Automatic volume slide command is interpreted like in STK files (rather than like in STP files) + SONG_FASTPORTAS = 0x01, // Portamentos are executed on every tick + SONG_FASTVOLSLIDES = 0x02, // Old Scream Tracker 3.0 volume slides (executed on every tick) + SONG_ITOLDEFFECTS = 0x04, // Old Impulse Tracker effect implementations + SONG_ITCOMPATGXX = 0x08, // IT "Compatible Gxx" (IT's flag to behave more like other trackers w/r/t portamento effects) + SONG_LINEARSLIDES = 0x10, // Linear slides vs. Amiga slides + SONG_EXFILTERRANGE = 0x20, // Cutoff Filter has double frequency range (up to ~10Khz) + SONG_AMIGALIMITS = 0x40, // Enforce amiga frequency limits + SONG_S3MOLDVIBRATO = 0x80, // ScreamTracker 2 vibrato in S3M files + SONG_PT_MODE = 0x100, // ProTracker 1/2 playback mode + SONG_ISAMIGA = 0x200, // Is an Amiga module and thus qualifies to be played using the Paula BLEP resampler + SONG_IMPORTED = 0x400, // Song type does not represent actual module format / was imported from a different format (OpenMPT) + SONG_PLAYALLSONGS = 0x800, // Play all subsongs consecutively (libopenmpt) + SONG_AUTO_TONEPORTA = 0x1000, // Tone portamento command is continued automatically + SONG_AUTO_TONEPORTA_CONT = 0x2000, // Auto tone portamento is not interruped by a tone portamento with parameter 0 + SONG_AUTO_GLOBALVOL = 0x4000, // Global volume slide command is continued automatically + SONG_AUTO_VIBRATO = 0x8000, // Vibrato command is continued automatically + SONG_AUTO_TREMOLO = 0x1'8000, // Tremolo command is continued automatically + SONG_AUTO_VOLSLIDE_STK = 0x2'0000, // Automatic volume slide command is interpreted like in STK files (rather than like in STP files) }; DECLARE_FLAGSET(SongFlags) Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp Sun May 26 00:37:33 2024 (r20852) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp Sun May 26 00:52:48 2024 (r20853) @@ -4366,7 +4366,7 @@ ModChannel &chn = playState.Chn[nChn]; chn.dwFlags.set(CHN_PORTAMENTO); if(m_SongFlags[SONG_AUTO_TONEPORTA]) - chn.autoSlide.SetActive(AutoSlideCommand::TonePortamento, param != 0); + chn.autoSlide.SetActive(AutoSlideCommand::TonePortamento, param != 0 || m_SongFlags[SONG_AUTO_TONEPORTA_CONT]); //IT compatibility 03: Share effect memory with portamento up/down if((!m_SongFlags[SONG_ITCOMPATGXX] && m_playBehaviour[kITPortaMemoryShare]) || GetType() == MOD_TYPE_PLM) |
|
From: <sv...@op...> - 2024-05-28 16:10:17
|
Author: sagamusix Date: Sun May 26 22:50:38 2024 New Revision: 20862 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20862 Log: Merged revision(s) 20847 from trunk/OpenMPT: [Fix] STP: Volume slide nibbles are not just swapped, but they are always both executed (so up and down are added together). [Ref] Cleanup STP loader. ........ Merged revision(s) 20861 from branches/OpenMPT-1.30: [Ref] Backport ModCommand::SetVolumeCommand and ModCommand::SetEffectCommand. ........ Modified: branches/OpenMPT-1.29/ (props changed) branches/OpenMPT-1.29/soundlib/Load_stp.cpp branches/OpenMPT-1.29/soundlib/modcommand.h Modified: branches/OpenMPT-1.29/soundlib/Load_stp.cpp ============================================================================== --- branches/OpenMPT-1.29/soundlib/Load_stp.cpp Sun May 26 22:49:37 2024 (r20861) +++ branches/OpenMPT-1.29/soundlib/Load_stp.cpp Sun May 26 22:50:38 2024 (r20862) @@ -441,18 +441,16 @@ const auto [instr, note, command, param] = file.ReadArray<uint8, 4>(); m.instr = instr; - m.note = note; m.param = param; - - if(m.note) + if(note) { - m.note += 24 + NOTE_MIN; + m.note = NOTE_MIDDLEC - 36 + note; chnMem = ChannelMemory(); } - // this is a nibble-swapped param value used for auto fine volside - // and auto global fine volside - uint8 swapped = (m.param >> 4) | (m.param << 4); + // Volume slides not only have their nibbles swapped, but the up and down parameters also add up + const int totalSlide = -static_cast<int>(m.param >> 4) + (m.param & 0x0F); + const uint8 slideParam = static_cast<uint8>((totalSlide > 0) ? totalSlide << 4 : -totalSlide); if((command & 0xF0) == 0xF0) { @@ -462,138 +460,93 @@ { m.param = mpt::saturate_round<ModCommand::PARAM>(ConvertTempo(ciaTempo).ToDouble()); m.command = CMD_TEMPO; - } else - { - m.command = CMD_NONE; } } else switch(command) { case 0x00: // arpeggio if(m.param) m.command = CMD_ARPEGGIO; - else - m.command = CMD_NONE; break; - case 0x01: // portamento up m.command = CMD_PORTAMENTOUP; break; - case 0x02: // portamento down m.command = CMD_PORTAMENTODOWN; break; - case 0x03: // auto fine portamento up chnMem.autoFinePorta = 0x10 | std::min(m.param, ModCommand::PARAM(15)); chnMem.autoPortaUp = 0; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x04: // auto fine portamento down chnMem.autoFinePorta = 0x20 | std::min(m.param, ModCommand::PARAM(15)); chnMem.autoPortaUp = 0; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x05: // auto portamento up chnMem.autoFinePorta = 0; chnMem.autoPortaUp = m.param; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x06: // auto portamento down chnMem.autoFinePorta = 0; chnMem.autoPortaUp = 0; chnMem.autoPortaDown = m.param; chnMem.autoTonePorta = 0; - - m.command = CMD_NONE; break; - case 0x07: // set global volume m.command = CMD_GLOBALVOLUME; globalVolSlide = 0; break; - case 0x08: // auto global fine volume slide - globalVolSlide = swapped; - m.command = CMD_NONE; + globalVolSlide = slideParam; break; - case 0x09: // fine portamento up m.command = CMD_MODCMDEX; m.param = 0x10 | std::min(m.param, ModCommand::PARAM(15)); break; - case 0x0A: // fine portamento down m.command = CMD_MODCMDEX; m.param = 0x20 | std::min(m.param, ModCommand::PARAM(15)); break; - case 0x0B: // auto fine volume slide - chnMem.autoVolSlide = swapped; - m.command = CMD_NONE; + chnMem.autoVolSlide = slideParam; break; - case 0x0C: // set volume m.volcmd = VOLCMD_VOLUME; m.vol = m.param; chnMem.autoVolSlide = 0; - m.command = CMD_NONE; break; - case 0x0D: // volume slide (param is swapped compared to .mod) - if(m.param & 0xF0) - { - m.volcmd = VOLCMD_VOLSLIDEDOWN; - m.vol = m.param >> 4; - } else if(m.param & 0x0F) - { - m.volcmd = VOLCMD_VOLSLIDEUP; - m.vol = m.param & 0xF; - } + if(totalSlide < 0) + m.SetVolumeCommand(VOLCMD_VOLSLIDEDOWN, slideParam & 0x0F); + else if(totalSlide > 0) + m.SetVolumeCommand(VOLCMD_VOLSLIDEUP, slideParam >> 4); chnMem.autoVolSlide = 0; - m.command = CMD_NONE; break; - case 0x0E: // set filter (also uses opposite value compared to .mod) - m.command = CMD_MODCMDEX; - m.param = 1 ^ (m.param ? 1 : 0); + m.SetEffectCommand(CMD_MODCMDEX, 1 ^ (m.param ? 1 : 0)); break; - case 0x0F: // set speed - m.command = CMD_SPEED; speedFrac = m.param & 0x0F; - m.param >>= 4; + m.SetEffectCommand(CMD_SPEED, m.param >> 4); break; - case 0x10: // auto vibrato chnMem.autoVibrato = m.param; chnMem.vibratoMem = 0; - m.command = CMD_NONE; break; - case 0x11: // auto tremolo if(m.param & 0xF) chnMem.autoTremolo = m.param; else chnMem.autoTremolo = 0; - m.command = CMD_NONE; break; - case 0x12: // pattern break m.command = CMD_PATTERNBREAK; break; - case 0x13: // auto tone portamento chnMem.autoFinePorta = 0; chnMem.autoPortaUp = 0; @@ -601,13 +554,10 @@ chnMem.autoTonePorta = m.param; chnMem.tonePortaMem = 0; - m.command = CMD_NONE; break; - case 0x14: // position jump m.command = CMD_POSITIONJUMP; break; - case 0x16: // start loop sequence if(m.instr && m.instr <= loopInfo.size()) { @@ -620,10 +570,7 @@ m.vol = m.param; } } - - m.command = CMD_NONE; break; - case 0x17: // play only loop nn if(m.instr && m.instr <= loopInfo.size()) { @@ -637,10 +584,7 @@ m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].looped); } } - - m.command = CMD_NONE; break; - case 0x18: // play sequence without loop if(m.instr && m.instr <= loopInfo.size()) { @@ -657,10 +601,7 @@ nonLooped[m.instr - 1] = ++m_nSamples; m.instr = static_cast<ModCommand::INSTR>(nonLooped[m.instr - 1]); } - - m.command = CMD_NONE; break; - case 0x19: // play only loop nn without loop if(m.instr && m.instr <= loopInfo.size()) { @@ -674,54 +615,37 @@ m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].nonLooped); } } - - m.command = CMD_NONE; break; - case 0x1D: // fine volume slide (nibble order also swapped) - m.command = CMD_VOLUMESLIDE; - m.param = swapped; - if(m.param & 0xF0) // slide down - m.param |= 0x0F; - else if(m.param & 0x0F) - m.param |= 0xF0; + if(totalSlide < 0) // slide down + m.SetEffectCommand(CMD_MODCMDEX, 0xB0 | (slideParam & 0x0F)); + else if(totalSlide > 0) + m.SetEffectCommand(CMD_MODCMDEX, 0xA0 | (slideParam >> 4)); break; - case 0x20: // "delayed fade" // just behave like either a normal fade or a notecut // depending on the speed if(m.param & 0xF0) { chnMem.autoVolSlide = m.param >> 4; - m.command = CMD_NONE; } else { - m.command = CMD_MODCMDEX; - m.param = 0xC0 | (m.param & 0xF); + m.SetEffectCommand(CMD_MODCMDEX, 0xC0 | (m.param & 0xF)); } break; - case 0x21: // note delay - m.command = CMD_MODCMDEX; - m.param = 0xD0 | std::min(m.param, ModCommand::PARAM(15)); + m.SetEffectCommand(CMD_MODCMDEX, 0xD0 | std::min(m.param, ModCommand::PARAM(15))); break; - case 0x22: // retrigger note - m.command = CMD_MODCMDEX; - m.param = 0x90 | std::min(m.param, ModCommand::PARAM(15)); + m.SetEffectCommand(CMD_MODCMDEX, 0x90 | std::min(m.param, ModCommand::PARAM(15))); break; - case 0x49: // set sample offset m.command = CMD_OFFSET; break; - case 0x4E: // other protracker commands (pattern loop / delay) if((m.param & 0xF0) == 0x60 || (m.param & 0xF0) == 0xE0) m.command = CMD_MODCMDEX; - else - m.command = CMD_NONE; break; - case 0x4F: // set speed/tempo if(m.param < 0x20) { @@ -732,9 +656,7 @@ m.command = CMD_TEMPO; } break; - default: - m.command = CMD_NONE; break; } Modified: branches/OpenMPT-1.29/soundlib/modcommand.h ============================================================================== --- branches/OpenMPT-1.29/soundlib/modcommand.h Sun May 26 22:49:37 2024 (r20861) +++ branches/OpenMPT-1.29/soundlib/modcommand.h Sun May 26 22:50:38 2024 (r20862) @@ -148,6 +148,13 @@ } bool operator!=(const ModCommand& mc) const { return !(*this == mc); } + MPT_FORCEINLINE void SetVolumeCommand(const VolumeCommand c, const VOL v) { volcmd = c; vol = v; } + MPT_FORCEINLINE void SetVolumeCommand(const std::pair<VolumeCommand, VOL> cmd) { volcmd = cmd.first; vol = cmd.second; } + MPT_FORCEINLINE void SetVolumeCommand(const ModCommand &other) { volcmd = other.volcmd; vol = other. vol; } + MPT_FORCEINLINE void SetEffectCommand(const EffectCommand c, const PARAM p) { command = c; param = p; } + MPT_FORCEINLINE void SetEffectCommand(const std::pair<EffectCommand, PARAM> cmd) { command = cmd.first; param = cmd.second; } + MPT_FORCEINLINE void SetEffectCommand(const ModCommand &other) { command = other.command; param = other.param; } + void Set(NOTE n, INSTR ins, uint16 volcol, uint16 effectcol) { note = n; instr = ins; SetValueVolCol(volcol); SetValueEffectCol(effectcol); } uint16 GetValueVolCol() const { return GetValueVolCol(volcmd, vol); } |
|
From: <sv...@op...> - 2024-05-28 16:05:22
|
Author: sagamusix Date: Sun May 26 22:48:18 2024 New Revision: 20860 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20860 Log: [Fix] Revert merge of r20847. Modified: branches/OpenMPT-1.29/ (props changed) branches/OpenMPT-1.29/soundlib/Load_stp.cpp Modified: branches/OpenMPT-1.29/soundlib/Load_stp.cpp ============================================================================== --- branches/OpenMPT-1.29/soundlib/Load_stp.cpp Sun May 26 22:42:37 2024 (r20859) +++ branches/OpenMPT-1.29/soundlib/Load_stp.cpp Sun May 26 22:48:18 2024 (r20860) @@ -441,16 +441,18 @@ const auto [instr, note, command, param] = file.ReadArray<uint8, 4>(); m.instr = instr; + m.note = note; m.param = param; - if(note) + + if(m.note) { - m.note = NOTE_MIDDLEC - 36 + note; + m.note += 24 + NOTE_MIN; chnMem = ChannelMemory(); } - // Volume slides not only have their nibbles swapped, but the up and down parameters also add up - const int totalSlide = -static_cast<int>(m.param >> 4) + (m.param & 0x0F); - const uint8 slideParam = static_cast<uint8>((totalSlide > 0) ? totalSlide << 4 : -totalSlide); + // this is a nibble-swapped param value used for auto fine volside + // and auto global fine volside + uint8 swapped = (m.param >> 4) | (m.param << 4); if((command & 0xF0) == 0xF0) { @@ -460,93 +462,138 @@ { m.param = mpt::saturate_round<ModCommand::PARAM>(ConvertTempo(ciaTempo).ToDouble()); m.command = CMD_TEMPO; + } else + { + m.command = CMD_NONE; } } else switch(command) { case 0x00: // arpeggio if(m.param) m.command = CMD_ARPEGGIO; + else + m.command = CMD_NONE; break; + case 0x01: // portamento up m.command = CMD_PORTAMENTOUP; break; + case 0x02: // portamento down m.command = CMD_PORTAMENTODOWN; break; + case 0x03: // auto fine portamento up chnMem.autoFinePorta = 0x10 | std::min(m.param, ModCommand::PARAM(15)); chnMem.autoPortaUp = 0; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; + + m.command = CMD_NONE; break; + case 0x04: // auto fine portamento down chnMem.autoFinePorta = 0x20 | std::min(m.param, ModCommand::PARAM(15)); chnMem.autoPortaUp = 0; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; + + m.command = CMD_NONE; break; + case 0x05: // auto portamento up chnMem.autoFinePorta = 0; chnMem.autoPortaUp = m.param; chnMem.autoPortaDown = 0; chnMem.autoTonePorta = 0; + + m.command = CMD_NONE; break; + case 0x06: // auto portamento down chnMem.autoFinePorta = 0; chnMem.autoPortaUp = 0; chnMem.autoPortaDown = m.param; chnMem.autoTonePorta = 0; + + m.command = CMD_NONE; break; + case 0x07: // set global volume m.command = CMD_GLOBALVOLUME; globalVolSlide = 0; break; + case 0x08: // auto global fine volume slide - globalVolSlide = slideParam; + globalVolSlide = swapped; + m.command = CMD_NONE; break; + case 0x09: // fine portamento up m.command = CMD_MODCMDEX; m.param = 0x10 | std::min(m.param, ModCommand::PARAM(15)); break; + case 0x0A: // fine portamento down m.command = CMD_MODCMDEX; m.param = 0x20 | std::min(m.param, ModCommand::PARAM(15)); break; + case 0x0B: // auto fine volume slide - chnMem.autoVolSlide = slideParam; + chnMem.autoVolSlide = swapped; + m.command = CMD_NONE; break; + case 0x0C: // set volume m.volcmd = VOLCMD_VOLUME; m.vol = m.param; chnMem.autoVolSlide = 0; + m.command = CMD_NONE; break; + case 0x0D: // volume slide (param is swapped compared to .mod) - if(totalSlide < 0) - m.SetVolumeCommand(VOLCMD_VOLSLIDEDOWN, slideParam & 0x0F); - else if(totalSlide > 0) - m.SetVolumeCommand(VOLCMD_VOLSLIDEUP, slideParam >> 4); + if(m.param & 0xF0) + { + m.volcmd = VOLCMD_VOLSLIDEDOWN; + m.vol = m.param >> 4; + } else if(m.param & 0x0F) + { + m.volcmd = VOLCMD_VOLSLIDEUP; + m.vol = m.param & 0xF; + } chnMem.autoVolSlide = 0; + m.command = CMD_NONE; break; + case 0x0E: // set filter (also uses opposite value compared to .mod) - m.SetEffectCommand(CMD_MODCMDEX, 1 ^ (m.param ? 1 : 0)); + m.command = CMD_MODCMDEX; + m.param = 1 ^ (m.param ? 1 : 0); break; + case 0x0F: // set speed + m.command = CMD_SPEED; speedFrac = m.param & 0x0F; - m.SetEffectCommand(CMD_SPEED, m.param >> 4); + m.param >>= 4; break; + case 0x10: // auto vibrato chnMem.autoVibrato = m.param; chnMem.vibratoMem = 0; + m.command = CMD_NONE; break; + case 0x11: // auto tremolo if(m.param & 0xF) chnMem.autoTremolo = m.param; else chnMem.autoTremolo = 0; + m.command = CMD_NONE; break; + case 0x12: // pattern break m.command = CMD_PATTERNBREAK; break; + case 0x13: // auto tone portamento chnMem.autoFinePorta = 0; chnMem.autoPortaUp = 0; @@ -554,10 +601,13 @@ chnMem.autoTonePorta = m.param; chnMem.tonePortaMem = 0; + m.command = CMD_NONE; break; + case 0x14: // position jump m.command = CMD_POSITIONJUMP; break; + case 0x16: // start loop sequence if(m.instr && m.instr <= loopInfo.size()) { @@ -570,7 +620,10 @@ m.vol = m.param; } } + + m.command = CMD_NONE; break; + case 0x17: // play only loop nn if(m.instr && m.instr <= loopInfo.size()) { @@ -584,7 +637,10 @@ m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].looped); } } + + m.command = CMD_NONE; break; + case 0x18: // play sequence without loop if(m.instr && m.instr <= loopInfo.size()) { @@ -601,7 +657,10 @@ nonLooped[m.instr - 1] = ++m_nSamples; m.instr = static_cast<ModCommand::INSTR>(nonLooped[m.instr - 1]); } + + m.command = CMD_NONE; break; + case 0x19: // play only loop nn without loop if(m.instr && m.instr <= loopInfo.size()) { @@ -615,37 +674,54 @@ m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].nonLooped); } } + + m.command = CMD_NONE; break; + case 0x1D: // fine volume slide (nibble order also swapped) - if(totalSlide < 0) // slide down - m.SetEffectCommand(CMD_MODCMDEX, 0xB0 | (slideParam & 0x0F)); - else if(totalSlide > 0) - m.SetEffectCommand(CMD_MODCMDEX, 0xA0 | (slideParam >> 4)); + m.command = CMD_VOLUMESLIDE; + m.param = swapped; + if(m.param & 0xF0) // slide down + m.param |= 0x0F; + else if(m.param & 0x0F) + m.param |= 0xF0; break; + case 0x20: // "delayed fade" // just behave like either a normal fade or a notecut // depending on the speed if(m.param & 0xF0) { chnMem.autoVolSlide = m.param >> 4; + m.command = CMD_NONE; } else { - m.SetEffectCommand(CMD_MODCMDEX, 0xC0 | (m.param & 0xF)); + m.command = CMD_MODCMDEX; + m.param = 0xC0 | (m.param & 0xF); } break; + case 0x21: // note delay - m.SetEffectCommand(CMD_MODCMDEX, 0xD0 | std::min(m.param, ModCommand::PARAM(15))); + m.command = CMD_MODCMDEX; + m.param = 0xD0 | std::min(m.param, ModCommand::PARAM(15)); break; + case 0x22: // retrigger note - m.SetEffectCommand(CMD_MODCMDEX, 0x90 | std::min(m.param, ModCommand::PARAM(15))); + m.command = CMD_MODCMDEX; + m.param = 0x90 | std::min(m.param, ModCommand::PARAM(15)); break; + case 0x49: // set sample offset m.command = CMD_OFFSET; break; + case 0x4E: // other protracker commands (pattern loop / delay) if((m.param & 0xF0) == 0x60 || (m.param & 0xF0) == 0xE0) m.command = CMD_MODCMDEX; + else + m.command = CMD_NONE; break; + case 0x4F: // set speed/tempo if(m.param < 0x20) { @@ -656,7 +732,9 @@ m.command = CMD_TEMPO; } break; + default: + m.command = CMD_NONE; break; } |
|
From: <sv...@op...> - 2024-05-28 16:05:22
|
Author: sagamusix Date: Sun May 26 22:49:37 2024 New Revision: 20861 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20861 Log: [Ref] Backport ModCommand::SetVolumeCommand and ModCommand::SetEffectCommand. Modified: branches/OpenMPT-1.30/soundlib/modcommand.h Modified: branches/OpenMPT-1.30/soundlib/modcommand.h ============================================================================== --- branches/OpenMPT-1.30/soundlib/modcommand.h Sun May 26 22:48:18 2024 (r20860) +++ branches/OpenMPT-1.30/soundlib/modcommand.h Sun May 26 22:49:37 2024 (r20861) @@ -151,6 +151,13 @@ } bool operator!=(const ModCommand& mc) const { return !(*this == mc); } + MPT_FORCEINLINE void SetVolumeCommand(const VolumeCommand c, const VOL v) { volcmd = c; vol = v; } + MPT_FORCEINLINE void SetVolumeCommand(const std::pair<VolumeCommand, VOL> cmd) { volcmd = cmd.first; vol = cmd.second; } + MPT_FORCEINLINE void SetVolumeCommand(const ModCommand &other) { volcmd = other.volcmd; vol = other. vol; } + MPT_FORCEINLINE void SetEffectCommand(const EffectCommand c, const PARAM p) { command = c; param = p; } + MPT_FORCEINLINE void SetEffectCommand(const std::pair<EffectCommand, PARAM> cmd) { command = cmd.first; param = cmd.second; } + MPT_FORCEINLINE void SetEffectCommand(const ModCommand &other) { command = other.command; param = other.param; } + void Set(NOTE n, INSTR ins, uint16 volcol, uint16 effectcol) { note = n; instr = ins; SetValueVolCol(volcol); SetValueEffectCol(effectcol); } uint16 GetValueVolCol() const { return GetValueVolCol(volcmd, vol); } |
|
From: <sv...@op...> - 2024-05-28 16:05:19
|
Author: sagamusix Date: Sat May 25 23:29:11 2024 New Revision: 20849 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20849 Log: [Imp] STK: Avoid importing auto slides if it's more likely that the commands are really supposesd to toggle the LED filter. Modified: trunk/OpenMPT/soundlib/Load_stk.cpp Modified: trunk/OpenMPT/soundlib/Load_stk.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_stk.cpp Sat May 25 23:04:22 2024 (r20848) +++ trunk/OpenMPT/soundlib/Load_stk.cpp Sat May 25 23:29:11 2024 (r20849) @@ -236,12 +236,13 @@ FileReader::pos_type patOffset = file.GetPosition(); - // Scan patterns to identify Ultimate Soundtracker modules. + // Scan patterns to identify Soundtracker versions and reject garbage. uint32 illegalBytes = 0, totalNumDxx = 0; + bool useAutoSlides = false; for(PATTERNINDEX pat = 0; pat < numPatterns; pat++) { const bool patternInUse = mpt::contains(Order(), pat); - uint8 numDxx = 0; + uint8 numDxx = 0, autoSlides = 0; uint8 emptyCmds = 0; MODPatternData patternData; file.ReadArray(patternData); @@ -318,6 +319,10 @@ break; } numDxx++; + } else if(eff == 0x0E) + { + if(param > 1 || ++autoSlides > 1) + useAutoSlides = true; } break; case 0x0F: @@ -395,7 +400,7 @@ { // Volume is sent as-is to the chip, which ignores the highest bit. param &= 0x7F; - } else if(command == 0x0E && (param > 0x01 || minVersion < ST_IX)) + } else if(command == 0x0E && (param > 0x01 || minVersion < ST_IX) && useAutoSlides) { // Import auto-slides as normal slides and fake them using volume column slides. command = 0x0A; |
|
From: <sv...@op...> - 2024-05-28 16:05:19
|
Author: sagamusix Date: Sun May 26 00:37:33 2024 New Revision: 20852 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20852 Log: [Fix] ULT: Do not clear portamento target with new note. Modified: trunk/OpenMPT/soundlib/Load_ult.cpp Modified: trunk/OpenMPT/soundlib/Load_ult.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_ult.cpp Sun May 26 00:31:50 2024 (r20851) +++ trunk/OpenMPT/soundlib/Load_ult.cpp Sun May 26 00:37:33 2024 (r20852) @@ -313,6 +313,7 @@ m_modFormat.charset = mpt::Charset::CP437; m_SongFlags = SONG_AUTO_TONEPORTA | SONG_ITCOMPATGXX | SONG_ITOLDEFFECTS; // this will be converted to IT format by MPT. + m_playBehaviour.reset(kITClearPortaTarget); // Read "messageLength" lines, each containing 32 characters. m_songMessage.ReadFixedLineLength(file, fileHeader.messageLength * 32, 32, 0); |
|
From: <sv...@op...> - 2024-05-23 18:30:09
|
Author: sagamusix Date: Thu May 23 20:29:56 2024 New Revision: 20845 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20845 Log: [Ref] Small cleanup. Modified: trunk/OpenMPT/soundlib/Load_pt36.cpp Modified: trunk/OpenMPT/soundlib/Load_pt36.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_pt36.cpp Thu May 23 20:29:29 2024 (r20844) +++ trunk/OpenMPT/soundlib/Load_pt36.cpp Thu May 23 20:29:56 2024 (r20845) @@ -1,6 +1,6 @@ /* - * Load_mod.cpp - * ------------ + * Load_pt36.cpp + * ------------- * Purpose: ProTracker 3.6 wrapper format loader * Notes : (currently none) * Authors: OpenMPT Devs @@ -10,7 +10,6 @@ #include "stdafx.h" #include "Loaders.h" -#include "MODTools.h" OPENMPT_NAMESPACE_BEGIN |
|
From: <sv...@op...> - 2024-05-23 18:29:38
|
Author: sagamusix Date: Thu May 23 20:29:29 2024 New Revision: 20844 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20844 Log: Merged revision(s) 20843 from trunk/OpenMPT: [Imp] MED: Try to combine effect commands when there are multiple pages. ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/soundlib/Load_med.cpp Modified: branches/OpenMPT-1.31/soundlib/Load_med.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_med.cpp Thu May 23 20:29:12 2024 (r20843) +++ branches/OpenMPT-1.31/soundlib/Load_med.cpp Thu May 23 20:29:29 2024 (r20844) @@ -568,7 +568,7 @@ ModCommand *m = pattern.GetpModCommand(row, 0); for(CHANNELINDEX chn = 0; chn < ctx.numTracks; chn++, m++) { - const auto oldCmd = std::make_pair(m->command, m->param); + auto oldCmd = std::make_pair(m->command, m->param); int note = NOTE_NONE; uint8 cmd = 0, param1 = 0, param2 = 0; if(ctx.version < 1) @@ -618,6 +618,8 @@ m->SetEffectCommand(oldCmd); else if(row > 0 && oldCmd.first == CMD_XPARAM) pattern.GetpModCommand(row - 1, chn)->param = Util::MaxValueOfType(m->param); + else if(!ModCommand::CombineEffects(m->command, m->param, oldCmd.first, oldCmd.second) && m->volcmd == VOLCMD_NONE) + m->FillInTwoCommands(m->command, m->param, oldCmd.first, oldCmd.second); } if(extraCmd.first != CMD_NONE) { |
|
From: <sv...@op...> - 2024-05-23 18:29:24
|
Author: sagamusix Date: Thu May 23 20:29:12 2024 New Revision: 20843 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20843 Log: [Imp] MED: Try to combine effect commands when there are multiple pages. Modified: trunk/OpenMPT/soundlib/Load_med.cpp Modified: trunk/OpenMPT/soundlib/Load_med.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp Thu May 23 20:24:26 2024 (r20842) +++ trunk/OpenMPT/soundlib/Load_med.cpp Thu May 23 20:29:12 2024 (r20843) @@ -591,7 +591,7 @@ ModCommand *m = pattern.GetpModCommand(row, 0); for(CHANNELINDEX chn = 0; chn < ctx.numTracks; chn++, m++) { - const auto oldCmd = std::make_pair(m->command, m->param); + auto oldCmd = std::make_pair(m->command, m->param); int note = NOTE_NONE; uint8 cmd = 0, param1 = 0, param2 = 0; if(ctx.version < 1) @@ -641,6 +641,8 @@ m->SetEffectCommand(oldCmd); else if(row > 0 && oldCmd.first == CMD_XPARAM) pattern.GetpModCommand(row - 1, chn)->param = Util::MaxValueOfType(m->param); + else if(!ModCommand::CombineEffects(m->command, m->param, oldCmd.first, oldCmd.second) && m->volcmd == VOLCMD_NONE) + m->FillInTwoCommands(m->command, m->param, oldCmd.first, oldCmd.second); } if(extraCmd.first != CMD_NONE) { |
|
From: <sv...@op...> - 2024-05-23 18:24:34
|
Author: sagamusix Date: Thu May 23 20:24:26 2024 New Revision: 20842 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20842 Log: Merged revision(s) 20841 from trunk/OpenMPT: [Imp] MED: Additional command pages can now be read (https://bugs.openmpt.org/view.php?id=1783). ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/soundlib/Load_med.cpp Modified: branches/OpenMPT-1.31/soundlib/Load_med.cpp ============================================================================== --- branches/OpenMPT-1.31/soundlib/Load_med.cpp Thu May 23 20:19:53 2024 (r20841) +++ branches/OpenMPT-1.31/soundlib/Load_med.cpp Thu May 23 20:24:26 2024 (r20842) @@ -392,53 +392,59 @@ } -static std::pair<EffectCommand, ModCommand::PARAM> ConvertMEDEffect(ModCommand &m, const uint8 command, const bool is8ch, const bool bpmMode, const uint8 rowsPerBeat, const bool volHex) +struct TranslateMEDPatternContext { - m.command = CMD_NONE; + const int16 transpose; + const CHANNELINDEX numTracks; + const uint8 version; + const uint8 rowsPerBeat; + const bool hardwareMixSamples : 1; + const bool is8Ch : 1; + const bool bpmMode : 1; + const bool volHex : 1; +}; + + +static std::pair<EffectCommand, ModCommand::PARAM> ConvertMEDEffect(ModCommand &m, const uint8 command, const uint8 param, const uint8 param2, const TranslateMEDPatternContext ctx) +{ + const uint8 nibbleLo = std::min(param, uint8(0x0F)); switch(command) { case 0x04: // Vibrato (twice as deep as in ProTracker) - m.command = CMD_VIBRATO; - m.param = (std::min<uint8>(m.param >> 3, 0x0F) << 4) | std::min<uint8>((m.param & 0x0F) * 2, 0x0F); + m.SetEffectCommand(CMD_VIBRATO, (std::min<uint8>(param >> 3, 0x0F) << 4) | std::min<uint8>((param & 0x0F) * 2, 0x0F)); break; case 0x08: // Hold and decay - m.command = CMD_NONE; break; case 0x09: // Set secondary speed - if(m.param > 0 && m.param <= 20) - m.command = CMD_SPEED; - else - m.command = CMD_NONE; + if(param > 0 && param <= 20) + m.SetEffectCommand(CMD_SPEED, param); break; case 0x0C: // Set Volume - m.command = CMD_VOLUME; - if(!volHex && m.param < 0x99) - m.param = (m.param >> 4) * 10 + (m.param & 0x0F); - else if(volHex) - m.param = ((m.param & 0x7F) + 1) / 2; - else - m.command = CMD_NONE; + if(!ctx.volHex && param < 0x99) + m.SetEffectCommand(CMD_VOLUME, static_cast<ModCommand::PARAM>((param >> 4) * 10 + (param & 0x0F))); + else if(ctx.volHex) + m.SetEffectCommand(CMD_VOLUME, static_cast<ModCommand::PARAM>(((param & 0x7F) + 1) / 2)); break; case 0x0D: - m.command = CMD_VOLUMESLIDE; + m.SetEffectCommand(CMD_VOLUMESLIDE, param); break; case 0x0E: // Synth jump m.command = CMD_NONE; break; case 0x0F: // Misc - if(m.param == 0) + if(param == 0) { - m.command = CMD_PATTERNBREAK; - } else if(m.param <= 0xF0) + m.SetEffectCommand(CMD_PATTERNBREAK, param); + } else if(param <= 0xF0) { m.command = CMD_TEMPO; - if(m.param < 0x03) + if(param < 0x03) { // This appears to be a bug in OctaMED which is not emulated in MED Soundstudio on Windows. m.param = 0x70; } else { - uint16 tempo = mpt::saturate_round<uint16>(MMDTempoToBPM(m.param, is8ch, bpmMode, rowsPerBeat).ToDouble()); + uint16 tempo = mpt::saturate_round<uint16>(MMDTempoToBPM(param, ctx.is8Ch, ctx.bpmMode, ctx.rowsPerBeat).ToDouble()); if(tempo <= Util::MaxValueOfType(m.param)) { m.param = static_cast<ModCommand::PARAM>(tempo); @@ -455,153 +461,177 @@ } else switch(command) { case 0xF1: // Play note twice - m.command = CMD_MODCMDEX; - m.param = 0x93; + m.SetEffectCommand(CMD_MODCMDEX, 0x93); break; case 0xF2: // Delay note - m.command = CMD_MODCMDEX; - m.param = 0xD3; + m.SetEffectCommand(CMD_MODCMDEX, 0xD3); break; case 0xF3: // Play note three times - m.command = CMD_MODCMDEX; - m.param = 0x92; + m.SetEffectCommand(CMD_MODCMDEX, 0x92); break; case 0xF8: // Turn filter off case 0xF9: // Turn filter on - m.command = CMD_MODCMDEX; - m.param = 0xF9 - m.param; + m.SetEffectCommand(CMD_MODCMDEX, 0xF9 - param); break; case 0xFA: // MIDI pedal on case 0xFB: // MIDI pedal off case 0xFD: // Set pitch case 0xFE: // End of song - m.command = CMD_NONE; break; case 0xFF: // Turn note off m.note = NOTE_NOTECUT; - m.command = CMD_NONE; - break; - default: - m.command = CMD_NONE; break; } break; case 0x10: // MIDI message - m.command = CMD_MIDI; - m.param |= 0x80; + m.SetEffectCommand(CMD_MIDI, param | 0x80); break; case 0x11: // Slide pitch up - m.command = CMD_MODCMDEX; - m.param = 0x10 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x10 | nibbleLo); break; case 0x12: // Slide pitch down - m.command = CMD_MODCMDEX; - m.param = 0x20 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x20 | nibbleLo); break; case 0x14: // Vibrato (ProTracker compatible depth, but faster) - m.command = CMD_VIBRATO; - m.param = (std::min<uint8>((m.param >> 4) + 1, 0x0F) << 4) | (m.param & 0x0F); + m.SetEffectCommand(CMD_VIBRATO, (std::min<uint8>((param >> 4) + 1, 0x0F) << 4) | (param & 0x0F)); break; case 0x15: // Set finetune - m.command = CMD_MODCMDEX; - m.param = 0x50 | (m.param & 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x50 | (param & 0x0F)); break; case 0x16: // Loop - m.command = CMD_MODCMDEX; - m.param = 0x60 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x60 | nibbleLo); break; case 0x18: // Stop note - m.command = CMD_MODCMDEX; - m.param = 0xC0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xC0 | nibbleLo); break; case 0x19: // Sample Offset - m.command = CMD_OFFSET; + m.SetEffectCommand(CMD_OFFSET, param); break; case 0x1A: // Slide volume up once - m.command = CMD_MODCMDEX; - m.param = 0xA0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xA0 | nibbleLo); break; case 0x1B: // Slide volume down once - m.command = CMD_MODCMDEX; - m.param = 0xB0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xB0 | nibbleLo); break; case 0x1C: // MIDI program - if(m.param > 0 && m.param <= 128) - { - m.command = CMD_MIDI; - m.param--; - } else - { - m.command = CMD_NONE; - } + if(param > 0 && param <= 128) + m.SetEffectCommand(CMD_MIDI, param - 1); break; case 0x1D: // Pattern break (in hex) - m.command = CMD_PATTERNBREAK; + m.SetEffectCommand(CMD_PATTERNBREAK, param); break; case 0x1E: // Repeat row - m.command = CMD_MODCMDEX; - m.param = 0xE0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xE0 | std::min<uint8>(param, 0x0F)); break; case 0x1F: // Note delay and retrigger { - if(m.param & 0xF0) - { - m.command = CMD_MODCMDEX; - m.param = 0xD0 | (m.param >> 4); - } else if(m.param & 0x0F) - { - m.command = CMD_MODCMDEX; - m.param = 0x90 | m.param; - } else - { - m.command = CMD_NONE; - } + if(param & 0xF0) + m.SetEffectCommand(CMD_MODCMDEX, 0xD0 | (param >> 4)); + else if(param & 0x0F) + m.SetEffectCommand(CMD_MODCMDEX, 0x90 | param); break; } case 0x20: // Reverse sample + skip samples - if(m.param == 0 && m.vol == 0) + if(param == 0 && param2 == 0) { if(m.IsNote()) { - m.command = CMD_S3MCMDEX; - m.param = 0x9F; + m.SetEffectCommand(CMD_XFINEPORTAUPDOWN, 0x9F); } } else { // Skip given number of samples - m.command = CMD_NONE; } break; case 0x29: // Relative sample offset - if(m.vol > 0) - { - m.command = CMD_OFFSETPERCENTAGE; - m.param = mpt::saturate_cast<ModCommand::PARAM>(Util::muldiv_unsigned(m.param, 0x100, m.vol)); - } else - { - m.command = CMD_NONE; - } + if(param2 > 0) + m.SetEffectCommand(CMD_OFFSETPERCENTAGE, mpt::saturate_cast<ModCommand::PARAM>(Util::muldiv_unsigned(param, 0x100, param2))); break; case 0x2E: // Set panning - if(m.param <= 0x10 || m.param >= 0xF0) - { - m.command = CMD_PANNING8; - m.param = mpt::saturate_cast<ModCommand::PARAM>(((m.param ^ 0x80) - 0x70) * 8); - } else - { - m.command = CMD_NONE; - } + if(param <= 0x10 || param >= 0xF0) + m.SetEffectCommand(CMD_PANNING8, mpt::saturate_cast<ModCommand::PARAM>(((param ^ 0x80) - 0x70) * 8)); break; default: - if(command < 0x10) - CSoundFile::ConvertModCommand(m, command, m.param); - else - m.command = CMD_NONE; + if((command > 0 || param) && command < 0x10) + CSoundFile::ConvertModCommand(m, command, param); break; } return std::make_pair(CMD_NONE, ModCommand::PARAM(0)); } + +static bool TranslateMEDPattern(FileReader &file, FileReader &cmdExt, CPattern &pattern, const TranslateMEDPatternContext ctx, const bool isExtraPage) +{ + bool needInstruments = false; + for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++) + { + ModCommand *m = pattern.GetpModCommand(row, 0); + for(CHANNELINDEX chn = 0; chn < ctx.numTracks; chn++, m++) + { + const auto oldCmd = std::make_pair(m->command, m->param); + int note = NOTE_NONE; + uint8 cmd = 0, param1 = 0, param2 = 0; + if(ctx.version < 1) + { + const auto [noteInstr, instrCmd, param] = file.ReadArray<uint8, 3>(); + + if(noteInstr & 0x3F) + note = (noteInstr & 0x3F) + ctx.transpose; + + m->instr = (instrCmd >> 4) | ((noteInstr & 0x80) >> 3) | ((noteInstr & 0x40) >> 1); + + cmd = instrCmd & 0x0F; + param1 = param; + } else if(isExtraPage) + { + const auto [command, param] = file.ReadArray<uint8, 2>(); + param2 = cmdExt.ReadUint8(); + cmd = command; + param1 = param; + } else + { + const auto [noteVal, instr, command, param] = file.ReadArray<uint8, 4>(); + param2 = cmdExt.ReadUint8(); + + if(noteVal & 0x7F) + note = (noteVal & 0x7F) + ctx.transpose; + else if(noteVal == 0x80) + m->note = NOTE_NOTECUT; + + if(instr & 0x3F) + m->instr = instr & 0x3F; + cmd = command; + param1 = param; + } + // Octave wrapping for 4-channel modules (TODO: this should not be set because of synth instruments) + if(ctx.hardwareMixSamples && note >= NOTE_MIDDLEC + 2 * 12) + needInstruments = true; + + if(note >= NOTE_MIN && note <= NOTE_MAX) + m->note = static_cast<ModCommand::NOTE>(note); + const auto extraCmd = ConvertMEDEffect(*m, cmd, param1, param2, ctx); + + if(oldCmd.first != CMD_NONE) + { + // Restore effect from previous page or X-Param if it was overwritten by an empty effect, or restrict to 8-bit value if this cell was overwritten with a "useful" effect + if(m->command == CMD_NONE) + m->SetEffectCommand(oldCmd); + else if(row > 0 && oldCmd.first == CMD_XPARAM) + pattern.GetpModCommand(row - 1, chn)->param = Util::MaxValueOfType(m->param); + } + if(extraCmd.first != CMD_NONE) + { + if(row < (pattern.GetNumRows() - 1)) + pattern.GetpModCommand(row + 1, chn)->SetEffectCommand(extraCmd); + else + m->param = Util::MaxValueOfType(m->param); // No space :( + } + } + } + return needInstruments; +} + + #ifdef MPT_WITH_VST static std::wstring ReadMEDStringUTF16BE(FileReader &file) { @@ -1318,8 +1348,9 @@ CHANNELINDEX numTracks; ROWINDEX numRows; std::string patName; - int transpose = NOTE_MIN + 47 + songHeader.playTranspose; - FileReader cmdExt; + int16 transpose = NOTE_MIN + 47 + songHeader.playTranspose; + uint16 numPages = 0; + FileReader cmdExt, commandPages; if(version < 1) { @@ -1346,11 +1377,20 @@ // We have now chased four pointers to get this far... lovely format. file.ReadString<mpt::String::maybeNullTerminated>(patName, blockInfo.nameLength); } + if(blockInfo.pageTableOffset + && file.Seek(blockInfo.pageTableOffset) + && file.CanRead(8)) + { + numPages = file.ReadUint16BE(); + file.Skip(2); + commandPages = file.ReadChunk(4 * numPages); + } + if(blockInfo.cmdExtTableOffset && file.Seek(blockInfo.cmdExtTableOffset) && file.Seek(file.ReadUint32BE())) { - cmdExt = file.ReadChunk(numTracks * numRows); + cmdExt = file.ReadChunk(numTracks * numRows * (1 + numPages)); } file.Seek(offset); @@ -1364,63 +1404,15 @@ pattern.SetName(patName); LimitMax(numTracks, m_nChannels); - for(ROWINDEX row = 0; row < numRows; row++) - { - ModCommand *m = pattern.GetpModCommand(row, 0); - for(CHANNELINDEX chn = 0; chn < numTracks; chn++, m++) - { - const auto oldCmd = std::make_pair(m->command, m->param); - int note = NOTE_NONE; - uint8 cmd = 0; - if(version < 1) - { - const auto [noteInstr, instrCmd, param] = file.ReadArray<uint8, 3>(); - - if(noteInstr & 0x3F) - note = (noteInstr & 0x3F) + transpose; - - m->instr = (instrCmd >> 4) | ((noteInstr & 0x80) >> 3) | ((noteInstr & 0x40) >> 1); - - cmd = instrCmd & 0x0F; - m->param = param; - } else - { - const auto [noteVal, instr, command, param1] = file.ReadArray<uint8, 4>(); - m->vol = cmdExt.ReadUint8(); - - if(noteVal & 0x7F) - note = (noteVal & 0x7F) + transpose; - else if(noteVal == 0x80) - m->note = NOTE_NOTECUT; - - m->instr = instr & 0x3F; - cmd = command; - m->param = param1; - } - // Octave wrapping for 4-channel modules (TODO: this should not be set because of synth instruments) - if(hardwareMixSamples && note >= NOTE_MIDDLEC + 2 * 12) - needInstruments = true; - - if(note >= NOTE_MIN && note <= NOTE_MAX) - m->note = static_cast<ModCommand::NOTE>(note); - const auto extraCmd = ConvertMEDEffect(*m, cmd, is8Ch, bpmMode, rowsPerBeat, volHex); + TranslateMEDPatternContext context{transpose, numTracks, version, rowsPerBeat, hardwareMixSamples, is8Ch, bpmMode, volHex}; + needInstruments |= TranslateMEDPattern(file, cmdExt, pattern, context, false); - if(oldCmd.first == CMD_XPARAM) - { - // Restore X-Param if it was overwritten by an empty effect, or restrict to 8-bit value if this cell was overwritten with a "useful" effect - if(m->command == CMD_NONE) - m->SetEffectCommand(oldCmd); - else if(row > 0) - pattern.GetpModCommand(row - 1, chn)->param = Util::MaxValueOfType(m->param); - } - if(extraCmd.first != CMD_NONE) - { - if(row < (numRows - 1)) - pattern.GetpModCommand(row + 1, chn)->SetEffectCommand(extraCmd); - else - m->param = Util::MaxValueOfType(m->param); // No space :( - } - } + for(uint16 page = 0; page < numPages; page++) + { + const uint32 pageOffset = commandPages.ReadUint32BE(); + if(!pageOffset || !file.Seek(pageOffset)) + continue; + TranslateMEDPattern(file, cmdExt, pattern, context, true); } } |
|
From: <sv...@op...> - 2024-05-23 18:20:02
|
Author: sagamusix Date: Thu May 23 20:19:53 2024 New Revision: 20841 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20841 Log: [Imp] MED: Additional command pages can now be read (https://bugs.openmpt.org/view.php?id=1783). Modified: trunk/OpenMPT/soundlib/Load_med.cpp Modified: trunk/OpenMPT/soundlib/Load_med.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Load_med.cpp Wed May 22 20:07:54 2024 (r20840) +++ trunk/OpenMPT/soundlib/Load_med.cpp Thu May 23 20:19:53 2024 (r20841) @@ -415,53 +415,59 @@ } -static std::pair<EffectCommand, ModCommand::PARAM> ConvertMEDEffect(ModCommand &m, const uint8 command, const bool is8ch, const bool bpmMode, const uint8 rowsPerBeat, const bool volHex) +struct TranslateMEDPatternContext { - m.command = CMD_NONE; + const int16 transpose; + const CHANNELINDEX numTracks; + const uint8 version; + const uint8 rowsPerBeat; + const bool hardwareMixSamples : 1; + const bool is8Ch : 1; + const bool bpmMode : 1; + const bool volHex : 1; +}; + + +static std::pair<EffectCommand, ModCommand::PARAM> ConvertMEDEffect(ModCommand &m, const uint8 command, const uint8 param, const uint8 param2, const TranslateMEDPatternContext ctx) +{ + const uint8 nibbleLo = std::min(param, uint8(0x0F)); switch(command) { case 0x04: // Vibrato (twice as deep as in ProTracker) - m.command = CMD_VIBRATO; - m.param = (std::min<uint8>(m.param >> 3, 0x0F) << 4) | std::min<uint8>((m.param & 0x0F) * 2, 0x0F); + m.SetEffectCommand(CMD_VIBRATO, (std::min<uint8>(param >> 3, 0x0F) << 4) | std::min<uint8>((param & 0x0F) * 2, 0x0F)); break; case 0x08: // Hold and decay - m.command = CMD_NONE; break; case 0x09: // Set secondary speed - if(m.param > 0 && m.param <= 20) - m.command = CMD_SPEED; - else - m.command = CMD_NONE; + if(param > 0 && param <= 20) + m.SetEffectCommand(CMD_SPEED, param); break; case 0x0C: // Set Volume - m.command = CMD_VOLUME; - if(!volHex && m.param < 0x99) - m.param = static_cast<ModCommand::PARAM>((m.param >> 4) * 10 + (m.param & 0x0F)); - else if(volHex) - m.param = static_cast<ModCommand::PARAM>(((m.param & 0x7F) + 1) / 2); - else - m.command = CMD_NONE; + if(!ctx.volHex && param < 0x99) + m.SetEffectCommand(CMD_VOLUME, static_cast<ModCommand::PARAM>((param >> 4) * 10 + (param & 0x0F))); + else if(ctx.volHex) + m.SetEffectCommand(CMD_VOLUME, static_cast<ModCommand::PARAM>(((param & 0x7F) + 1) / 2)); break; case 0x0D: - m.command = CMD_VOLUMESLIDE; + m.SetEffectCommand(CMD_VOLUMESLIDE, param); break; case 0x0E: // Synth jump / MIDI panning - m.command = CMD_MED_SYNTH_JUMP; + m.SetEffectCommand(CMD_MED_SYNTH_JUMP, param); break; case 0x0F: // Misc - if(m.param == 0) + if(param == 0) { - m.command = CMD_PATTERNBREAK; - } else if(m.param <= 0xF0) + m.SetEffectCommand(CMD_PATTERNBREAK, param); + } else if(param <= 0xF0) { m.command = CMD_TEMPO; - if(m.param < 0x03) + if(param < 0x03) { // This appears to be a bug in OctaMED which is not emulated in MED Soundstudio on Windows. m.param = 0x70; } else { - uint16 tempo = mpt::saturate_round<uint16>(MMDTempoToBPM(m.param, is8ch, bpmMode, rowsPerBeat).ToDouble()); + uint16 tempo = mpt::saturate_round<uint16>(MMDTempoToBPM(param, ctx.is8Ch, ctx.bpmMode, ctx.rowsPerBeat).ToDouble()); if(tempo <= Util::MaxValueOfType(m.param)) { m.param = static_cast<ModCommand::PARAM>(tempo); @@ -478,154 +484,177 @@ } else switch(command) { case 0xF1: // Play note twice - m.command = CMD_MODCMDEX; - m.param = 0x93; + m.SetEffectCommand(CMD_MODCMDEX, 0x93); break; case 0xF2: // Delay note - m.command = CMD_MODCMDEX; - m.param = 0xD3; + m.SetEffectCommand(CMD_MODCMDEX, 0xD3); break; case 0xF3: // Play note three times - m.command = CMD_MODCMDEX; - m.param = 0x92; + m.SetEffectCommand(CMD_MODCMDEX, 0x92); break; case 0xF8: // Turn filter off case 0xF9: // Turn filter on - m.command = CMD_MODCMDEX; - m.param = 0xF9 - m.param; + m.SetEffectCommand(CMD_MODCMDEX, 0xF9 - param); break; case 0xFA: // MIDI pedal on case 0xFB: // MIDI pedal off case 0xFD: // Set pitch case 0xFE: // End of song - m.command = CMD_NONE; break; case 0xFF: // Turn note off m.note = NOTE_NOTECUT; - m.command = CMD_NONE; - break; - default: - m.command = CMD_NONE; break; } break; case 0x10: // MIDI message - m.command = CMD_MIDI; - m.param |= 0x80; + m.SetEffectCommand(CMD_MIDI, param | 0x80); break; case 0x11: // Slide pitch up - m.command = CMD_MODCMDEX; - m.param = 0x10 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x10 | nibbleLo); break; case 0x12: // Slide pitch down - m.command = CMD_MODCMDEX; - m.param = 0x20 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x20 | nibbleLo); break; case 0x14: // Vibrato (ProTracker compatible depth, but faster) - m.command = CMD_VIBRATO; - m.param = (std::min<uint8>((m.param >> 4) + 1, 0x0F) << 4) | (m.param & 0x0F); + m.SetEffectCommand(CMD_VIBRATO, (std::min<uint8>((param >> 4) + 1, 0x0F) << 4) | (param & 0x0F)); break; case 0x15: // Set finetune - m.command = CMD_MODCMDEX; - m.param = 0x50 | (m.param & 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x50 | (param & 0x0F)); break; case 0x16: // Loop - m.command = CMD_MODCMDEX; - m.param = 0x60 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0x60 | nibbleLo); break; case 0x18: // Stop note - m.command = CMD_MODCMDEX; - m.param = 0xC0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xC0 | nibbleLo); break; case 0x19: // Sample Offset - m.command = CMD_OFFSET; + m.SetEffectCommand(CMD_OFFSET, param); break; case 0x1A: // Slide volume up once - m.command = CMD_MODCMDEX; - m.param = 0xA0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xA0 | nibbleLo); break; case 0x1B: // Slide volume down once - m.command = CMD_MODCMDEX; - m.param = 0xB0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xB0 | nibbleLo); break; case 0x1C: // MIDI program - if(m.param > 0 && m.param <= 128) - { - m.command = CMD_MIDI; - m.param--; - } else - { - m.command = CMD_NONE; - } + if(param > 0 && param <= 128) + m.SetEffectCommand(CMD_MIDI, param - 1); break; case 0x1D: // Pattern break (in hex) - m.command = CMD_PATTERNBREAK; + m.SetEffectCommand(CMD_PATTERNBREAK, param); break; case 0x1E: // Repeat row - m.command = CMD_MODCMDEX; - m.param = 0xE0 | std::min<uint8>(m.param, 0x0F); + m.SetEffectCommand(CMD_MODCMDEX, 0xE0 | std::min<uint8>(param, 0x0F)); break; case 0x1F: // Note delay and retrigger { - if(m.param & 0xF0) - { - m.command = CMD_MODCMDEX; - m.param = 0xD0 | (m.param >> 4); - } else if(m.param & 0x0F) - { - m.command = CMD_MODCMDEX; - m.param = 0x90 | m.param; - } else - { - m.command = CMD_NONE; - } + if(param & 0xF0) + m.SetEffectCommand(CMD_MODCMDEX, 0xD0 | (param >> 4)); + else if(param & 0x0F) + m.SetEffectCommand(CMD_MODCMDEX, 0x90 | param); break; } case 0x20: // Reverse sample + skip samples - if(m.param == 0 && m.vol == 0) + if(param == 0 && param2 == 0) { if(m.IsNote()) { - m.command = CMD_S3MCMDEX; - m.param = 0x9F; + m.SetEffectCommand(CMD_XFINEPORTAUPDOWN, 0x9F); } } else { // Skip given number of samples - m.command = CMD_NONE; } break; case 0x29: // Relative sample offset - if(m.vol > 0) - { - m.command = CMD_OFFSETPERCENTAGE; - m.param = mpt::saturate_cast<ModCommand::PARAM>(Util::muldiv_unsigned(m.param, 0x100, m.vol)); - } else - { - m.command = CMD_NONE; - } + if(param2 > 0) + m.SetEffectCommand(CMD_OFFSETPERCENTAGE, mpt::saturate_cast<ModCommand::PARAM>(Util::muldiv_unsigned(param, 0x100, param2))); break; case 0x2E: // Set panning - if(m.param <= 0x10 || m.param >= 0xF0) - { - m.command = CMD_PANNING8; - m.param = mpt::saturate_cast<ModCommand::PARAM>(((m.param ^ 0x80) - 0x70) * 8); - } else - { - m.command = CMD_NONE; - } + if(param <= 0x10 || param >= 0xF0) + m.SetEffectCommand(CMD_PANNING8, mpt::saturate_cast<ModCommand::PARAM>(((param ^ 0x80) - 0x70) * 8)); break; default: - if(command < 0x10) - CSoundFile::ConvertModCommand(m, command, m.param); - else - m.command = CMD_NONE; + if((command > 0 || param) && command < 0x10) + CSoundFile::ConvertModCommand(m, command, param); break; } return std::make_pair(CMD_NONE, ModCommand::PARAM(0)); } +static bool TranslateMEDPattern(FileReader &file, FileReader &cmdExt, CPattern &pattern, const TranslateMEDPatternContext ctx, const bool isExtraPage) +{ + bool needInstruments = false; + for(ROWINDEX row = 0; row < pattern.GetNumRows(); row++) + { + ModCommand *m = pattern.GetpModCommand(row, 0); + for(CHANNELINDEX chn = 0; chn < ctx.numTracks; chn++, m++) + { + const auto oldCmd = std::make_pair(m->command, m->param); + int note = NOTE_NONE; + uint8 cmd = 0, param1 = 0, param2 = 0; + if(ctx.version < 1) + { + const auto [noteInstr, instrCmd, param] = file.ReadArray<uint8, 3>(); + + if(noteInstr & 0x3F) + note = (noteInstr & 0x3F) + ctx.transpose; + + m->instr = (instrCmd >> 4) | ((noteInstr & 0x80) >> 3) | ((noteInstr & 0x40) >> 1); + + cmd = instrCmd & 0x0F; + param1 = param; + } else if(isExtraPage) + { + const auto [command, param] = file.ReadArray<uint8, 2>(); + param2 = cmdExt.ReadUint8(); + cmd = command; + param1 = param; + } else + { + const auto [noteVal, instr, command, param] = file.ReadArray<uint8, 4>(); + param2 = cmdExt.ReadUint8(); + + if(noteVal & 0x7F) + note = (noteVal & 0x7F) + ctx.transpose; + else if(noteVal == 0x80) + m->note = NOTE_NOTECUT; + + if(instr & 0x3F) + m->instr = instr & 0x3F; + cmd = command; + param1 = param; + } + // Octave wrapping for 4-channel modules (TODO: this should not be set because of synth instruments) + if(ctx.hardwareMixSamples && note >= NOTE_MIDDLEC + 2 * 12) + needInstruments = true; + + if(note >= NOTE_MIN && note <= NOTE_MAX) + m->note = static_cast<ModCommand::NOTE>(note); + const auto extraCmd = ConvertMEDEffect(*m, cmd, param1, param2, ctx); + + if(oldCmd.first != CMD_NONE) + { + // Restore effect from previous page or X-Param if it was overwritten by an empty effect, or restrict to 8-bit value if this cell was overwritten with a "useful" effect + if(m->command == CMD_NONE) + m->SetEffectCommand(oldCmd); + else if(row > 0 && oldCmd.first == CMD_XPARAM) + pattern.GetpModCommand(row - 1, chn)->param = Util::MaxValueOfType(m->param); + } + if(extraCmd.first != CMD_NONE) + { + if(row < (pattern.GetNumRows() - 1)) + pattern.GetpModCommand(row + 1, chn)->SetEffectCommand(extraCmd); + else + m->param = Util::MaxValueOfType(m->param); // No space :( + } + } + } + return needInstruments; +} + + static void TranslateMEDSynthScript(std::array<uint8, 128> &arr, size_t numEntries, uint8 speed, uint8 hold, uint8 decay, InstrumentSynth::Events &events, bool isVolume) { events.push_back(InstrumentSynth::Event::SetStepSpeed(speed)); @@ -1498,8 +1527,9 @@ CHANNELINDEX numTracks; ROWINDEX numRows; std::string patName; - int transpose = NOTE_MIN + 47 + songHeader.playTranspose; - FileReader cmdExt; + int16 transpose = NOTE_MIN + 47 + songHeader.playTranspose; + uint16 numPages = 0; + FileReader cmdExt, commandPages; if(version < 1) { @@ -1526,11 +1556,20 @@ // We have now chased four pointers to get this far... lovely format. file.ReadString<mpt::String::maybeNullTerminated>(patName, blockInfo.nameLength); } + if(blockInfo.pageTableOffset + && file.Seek(blockInfo.pageTableOffset) + && file.CanRead(8)) + { + numPages = file.ReadUint16BE(); + file.Skip(2); + commandPages = file.ReadChunk(4 * numPages); + } + if(blockInfo.cmdExtTableOffset && file.Seek(blockInfo.cmdExtTableOffset) && file.Seek(file.ReadUint32BE())) { - cmdExt = file.ReadChunk(numTracks * numRows); + cmdExt = file.ReadChunk(numTracks * numRows * (1 + numPages)); } file.Seek(offset); @@ -1544,63 +1583,15 @@ pattern.SetName(patName); LimitMax(numTracks, m_nChannels); - for(ROWINDEX row = 0; row < numRows; row++) - { - ModCommand *m = pattern.GetpModCommand(row, 0); - for(CHANNELINDEX chn = 0; chn < numTracks; chn++, m++) - { - const auto oldCmd = std::make_pair(m->command, m->param); - int note = NOTE_NONE; - uint8 cmd = 0; - if(version < 1) - { - const auto [noteInstr, instrCmd, param] = file.ReadArray<uint8, 3>(); - - if(noteInstr & 0x3F) - note = (noteInstr & 0x3F) + transpose; - - m->instr = (instrCmd >> 4) | ((noteInstr & 0x80) >> 3) | ((noteInstr & 0x40) >> 1); - - cmd = instrCmd & 0x0F; - m->param = param; - } else - { - const auto [noteVal, instr, command, param1] = file.ReadArray<uint8, 4>(); - m->vol = cmdExt.ReadUint8(); - - if(noteVal & 0x7F) - note = (noteVal & 0x7F) + transpose; - else if(noteVal == 0x80) - m->note = NOTE_NOTECUT; - - m->instr = instr & 0x3F; - cmd = command; - m->param = param1; - } - // Octave wrapping for 4-channel modules (TODO: this should not be set because of synth instruments) - if(hardwareMixSamples && note >= NOTE_MIDDLEC + 2 * 12) - needInstruments = true; - - if(note >= NOTE_MIN && note <= NOTE_MAX) - m->note = static_cast<ModCommand::NOTE>(note); - const auto extraCmd = ConvertMEDEffect(*m, cmd, is8Ch, bpmMode, rowsPerBeat, volHex); + TranslateMEDPatternContext context{transpose, numTracks, version, rowsPerBeat, hardwareMixSamples, is8Ch, bpmMode, volHex}; + needInstruments |= TranslateMEDPattern(file, cmdExt, pattern, context, false); - if(oldCmd.first == CMD_XPARAM) - { - // Restore X-Param if it was overwritten by an empty effect, or restrict to 8-bit value if this cell was overwritten with a "useful" effect - if(m->command == CMD_NONE) - m->SetEffectCommand(oldCmd); - else if(row > 0) - pattern.GetpModCommand(row - 1, chn)->param = Util::MaxValueOfType(m->param); - } - if(extraCmd.first != CMD_NONE) - { - if(row < (numRows - 1)) - pattern.GetpModCommand(row + 1, chn)->SetEffectCommand(extraCmd); - else - m->param = Util::MaxValueOfType(m->param); // No space :( - } - } + for(uint16 page = 0; page < numPages; page++) + { + const uint32 pageOffset = commandPages.ReadUint32BE(); + if(!pageOffset || !file.Seek(pageOffset)) + continue; + TranslateMEDPattern(file, cmdExt, pattern, context, true); } } |
|
From: <sv...@op...> - 2024-05-22 18:08:01
|
Author: sagamusix Date: Wed May 22 20:07:54 2024 New Revision: 20840 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20840 Log: Merged revision(s) 20839 from trunk/OpenMPT: [Fix] Navigating up on row 0 in a pattern with "Play whole row while navigating" enabled "but "Continuous scroll" disabled played the row and advanced to row 1 instead of doing nothing (https://bugs.openmpt.org/view.php?id=1781). ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/mptrack/View_pat.cpp Modified: branches/OpenMPT-1.31/mptrack/View_pat.cpp ============================================================================== --- branches/OpenMPT-1.31/mptrack/View_pat.cpp Wed May 22 20:07:11 2024 (r20839) +++ branches/OpenMPT-1.31/mptrack/View_pat.cpp Wed May 22 20:07:54 2024 (r20840) @@ -4256,12 +4256,9 @@ sndFile.m_PlayState.m_nNextOrder++; } CMainFrame::GetMainFrame()->ResetNotificationBuffer(); - } else + } else if(row != ROWINDEX_INVALID && (TrackerSettings::Instance().m_dwPatternSetup & PATTERN_PLAYNAVIGATEROW)) { - if(TrackerSettings::Instance().m_dwPatternSetup & PATTERN_PLAYNAVIGATEROW) - { - PatternStep(row); - } + PatternStep(row); } } |
|
From: <sv...@op...> - 2024-05-22 18:07:24
|
Author: sagamusix Date: Wed May 22 20:07:11 2024 New Revision: 20839 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20839 Log: [Fix] Navigating up on row 0 in a pattern with "Play whole row while navigating" enabled "but "Continuous scroll" disabled played the row and advanced to row 1 instead of doing nothing (https://bugs.openmpt.org/view.php?id=1781). Modified: trunk/OpenMPT/mptrack/View_pat.cpp Modified: trunk/OpenMPT/mptrack/View_pat.cpp ============================================================================== --- trunk/OpenMPT/mptrack/View_pat.cpp Wed May 22 19:51:08 2024 (r20838) +++ trunk/OpenMPT/mptrack/View_pat.cpp Wed May 22 20:07:11 2024 (r20839) @@ -4305,12 +4305,9 @@ sndFile.m_PlayState.m_nNextOrder++; } CMainFrame::GetMainFrame()->ResetNotificationBuffer(); - } else + } else if(row != ROWINDEX_INVALID && (TrackerSettings::Instance().m_dwPatternSetup & PATTERN_PLAYNAVIGATEROW)) { - if(TrackerSettings::Instance().m_dwPatternSetup & PATTERN_PLAYNAVIGATEROW) - { - PatternStep(row); - } + PatternStep(row); } } |
|
From: <sv...@op...> - 2024-05-22 17:51:15
|
Author: sagamusix Date: Wed May 22 19:51:08 2024 New Revision: 20838 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20838 Log: [Fix] Instrument tab: Setting an instrument's plugin assignment to "no plugin" broke in r20669 (https://bugs.openmpt.org/view.php?id=1782). Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp Modified: trunk/OpenMPT/mptrack/Ctrl_ins.cpp ============================================================================== --- trunk/OpenMPT/mptrack/Ctrl_ins.cpp Wed May 22 11:11:00 2024 (r20837) +++ trunk/OpenMPT/mptrack/Ctrl_ins.cpp Wed May 22 19:51:08 2024 (r20838) @@ -2478,19 +2478,20 @@ bool wasOpenedWithMouse = m_openendPluginListWithMouse; m_openendPluginListWithMouse = false; - if (pIns) + if(pIns) { BOOL enableVol = (nPlug == PLUGINDEX_INVALID || m_sndFile.m_playBehaviour[kMIDICCBugEmulation]) ? FALSE : TRUE; velocityStyle.EnableWindow(enableVol); m_CbnPluginVolumeHandling.EnableWindow(enableVol); - if(nPlug < MAX_MIXPLUGINS) + const PLUGINDEX mixPlug = (nPlug != PLUGINDEX_INVALID) ? nPlug + 1 : 0; + if(mixPlug <= MAX_MIXPLUGINS) { bool active = !IsLocked(); - if (active && pIns->nMixPlug != (nPlug + 1)) + if(active && pIns->nMixPlug != mixPlug) { PrepareUndo("Set Plugin"); - pIns->nMixPlug = nPlug + 1; + pIns->nMixPlug = mixPlug; SetModified(InstrumentHint().Info(), false); } @@ -2513,7 +2514,7 @@ { m_modDoc.SetModified(); } - m_modDoc.UpdateAllViews(nullptr, PluginHint(nPlug + 1).Info().Names()); + m_modDoc.UpdateAllViews(nullptr, PluginHint(mixPlug).Info().Names()); } } |
|
From: <sv...@op...> - 2024-05-22 09:11:12
|
Author: manx Date: Wed May 22 11:11:00 2024 New Revision: 20837 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20837 Log: Merged revision(s) 20835 from trunk/OpenMPT: [Ref] mpt/base/detect_compiler.hpp: Detect VS2022 19.10. ........ Modified: branches/OpenMPT-1.30/ (props changed) branches/OpenMPT-1.30/src/mpt/base/detect_compiler.hpp Modified: branches/OpenMPT-1.30/src/mpt/base/detect_compiler.hpp ============================================================================== --- branches/OpenMPT-1.30/src/mpt/base/detect_compiler.hpp Wed May 22 11:10:28 2024 (r20836) +++ branches/OpenMPT-1.30/src/mpt/base/detect_compiler.hpp Wed May 22 11:11:00 2024 (r20837) @@ -50,7 +50,9 @@ #elif defined(_MSC_VER) #define MPT_COMPILER_MSVC 1 -#if (_MSC_VER >= 1939) +#if (_MSC_VER >= 1940) +#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 10) +#elif (_MSC_VER >= 1939) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 9) #elif (_MSC_VER >= 1938) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 8) |
|
From: <sv...@op...> - 2024-05-22 09:10:40
|
Author: manx Date: Wed May 22 11:10:28 2024 New Revision: 20836 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20836 Log: Merged revision(s) 20835 from trunk/OpenMPT: [Ref] mpt/base/detect_compiler.hpp: Detect VS2022 19.10. ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/src/mpt/base/detect_compiler.hpp Modified: branches/OpenMPT-1.31/src/mpt/base/detect_compiler.hpp ============================================================================== --- branches/OpenMPT-1.31/src/mpt/base/detect_compiler.hpp Wed May 22 11:09:56 2024 (r20835) +++ branches/OpenMPT-1.31/src/mpt/base/detect_compiler.hpp Wed May 22 11:10:28 2024 (r20836) @@ -50,7 +50,9 @@ #elif defined(_MSC_VER) #define MPT_COMPILER_MSVC 1 -#if (_MSC_VER >= 1939) +#if (_MSC_VER >= 1940) +#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 10) +#elif (_MSC_VER >= 1939) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 9) #elif (_MSC_VER >= 1938) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 8) |
|
From: <sv...@op...> - 2024-05-22 09:10:08
|
Author: manx Date: Wed May 22 11:09:56 2024 New Revision: 20835 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20835 Log: [Ref] mpt/base/detect_compiler.hpp: Detect VS2022 19.10. Modified: trunk/OpenMPT/src/mpt/base/detect_compiler.hpp Modified: trunk/OpenMPT/src/mpt/base/detect_compiler.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/detect_compiler.hpp Wed May 22 11:08:02 2024 (r20834) +++ trunk/OpenMPT/src/mpt/base/detect_compiler.hpp Wed May 22 11:09:56 2024 (r20835) @@ -50,7 +50,9 @@ #elif defined(_MSC_VER) #define MPT_COMPILER_MSVC 1 -#if (_MSC_VER >= 1939) +#if (_MSC_VER >= 1940) +#define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 10) +#elif (_MSC_VER >= 1939) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 9) #elif (_MSC_VER >= 1938) #define MPT_COMPILER_MSVC_VERSION MPT_COMPILER_MAKE_VERSION2(2022, 8) |
|
From: <sv...@op...> - 2024-05-22 09:08:14
|
Author: manx Date: Wed May 22 11:08:02 2024 New Revision: 20834 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20834 Log: Merged revision(s) 20833 from trunk/OpenMPT: [Fix] mpt/base/detect_os.hpp: Early Windows 10 Preview versions used NT Version 6.4. [Fix] mpt/osinfo/windows_version.hpp: Early Windows 10 Preview versions used NT Version 6.4. ........ Modified: branches/OpenMPT-1.31/ (props changed) branches/OpenMPT-1.31/misc/mptOS.cpp branches/OpenMPT-1.31/src/mpt/base/detect_os.hpp branches/OpenMPT-1.31/src/mpt/osinfo/windows_version.hpp Modified: branches/OpenMPT-1.31/misc/mptOS.cpp ============================================================================== --- branches/OpenMPT-1.31/misc/mptOS.cpp Wed May 22 11:07:35 2024 (r20833) +++ branches/OpenMPT-1.31/misc/mptOS.cpp Wed May 22 11:08:02 2024 (r20834) @@ -53,6 +53,7 @@ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 14393, 0 }, UL_("Windows 10 1607"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10586, 0 }, UL_("Windows 10 1511"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10240, 0 }, UL_("Windows 10 1507"), true }, + { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10Pre, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 10 Preview"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8.1"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win8, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win7, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 7"), true }, Modified: branches/OpenMPT-1.31/src/mpt/base/detect_os.hpp ============================================================================== --- branches/OpenMPT-1.31/src/mpt/base/detect_os.hpp Wed May 22 11:07:35 2024 (r20833) +++ branches/OpenMPT-1.31/src/mpt/base/detect_os.hpp Wed May 22 11:08:02 2024 (r20834) @@ -41,6 +41,7 @@ #define MPT_WIN_8 MPT_WIN_MAKE_VERSION(0x06, 0x02, 0x00, 0x00) #define MPT_WIN_81 MPT_WIN_MAKE_VERSION(0x06, 0x03, 0x00, 0x00) +#define MPT_WIN_10_PRE MPT_WIN_MAKE_VERSION(0x06, 0x04, 0x00, 0x00) #define MPT_WIN_10 MPT_WIN_MAKE_VERSION(0x0a, 0x00, 0x00, 0x00) // NTDDI_WIN10 1507 #define MPT_WIN_10_1511 MPT_WIN_MAKE_VERSION(0x0a, 0x00, 0x00, 0x01) // NTDDI_WIN10_TH2 1511 #define MPT_WIN_10_1607 MPT_WIN_MAKE_VERSION(0x0a, 0x00, 0x00, 0x02) // NTDDI_WIN10_RS1 1607 Modified: branches/OpenMPT-1.31/src/mpt/osinfo/windows_version.hpp ============================================================================== --- branches/OpenMPT-1.31/src/mpt/osinfo/windows_version.hpp Wed May 22 11:07:35 2024 (r20833) +++ branches/OpenMPT-1.31/src/mpt/osinfo/windows_version.hpp Wed May 22 11:08:02 2024 (r20834) @@ -38,6 +38,7 @@ Win7 = 0x0000000600000001ull, Win8 = 0x0000000600000002ull, Win81 = 0x0000000600000003ull, + Win10Pre = 0x0000000600000004ull, Win10 = 0x0000000a00000000ull, WinNewer = Win10 + 1ull }; @@ -162,6 +163,8 @@ return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack(0, 0), 10586, 0); #elif MPT_WINNT_AT_LEAST(MPT_WIN_10) // 1507 return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack(0, 0), 10240, 0); +#elif MPT_WINNT_AT_LEAST(MPT_WIN_10_PRE) + return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win10Pre, mpt::osinfo::windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0, 0); #elif MPT_WINNT_AT_LEAST(MPT_WIN_81) return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0, 0); #elif MPT_WINNT_AT_LEAST(MPT_WIN_8) |
|
From: <sv...@op...> - 2024-05-22 09:07:43
|
Author: manx Date: Wed May 22 11:07:35 2024 New Revision: 20833 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20833 Log: [Fix] mpt/base/detect_os.hpp: Early Windows 10 Preview versions used NT Version 6.4. [Fix] mpt/osinfo/windows_version.hpp: Early Windows 10 Preview versions used NT Version 6.4. Modified: trunk/OpenMPT/misc/mptOS.cpp trunk/OpenMPT/src/mpt/base/detect_os.hpp trunk/OpenMPT/src/mpt/osinfo/windows_version.hpp Modified: trunk/OpenMPT/misc/mptOS.cpp ============================================================================== --- trunk/OpenMPT/misc/mptOS.cpp Mon May 20 21:01:14 2024 (r20832) +++ trunk/OpenMPT/misc/mptOS.cpp Wed May 22 11:07:35 2024 (r20833) @@ -53,6 +53,7 @@ { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 14393, 0 }, UL_("Windows 10 1607"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10586, 0 }, UL_("Windows 10 1511"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 10240, 0 }, UL_("Windows 10 1507"), true }, + { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win10Pre, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 10 Preview"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8.1"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win8, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 8"), true }, { mpt::osinfo::windows::Version{ mpt::osinfo::windows::Version::Win7, mpt::osinfo::windows::Version::ServicePack{ 0, 0 }, 0, 0 }, UL_("Windows 7"), true }, Modified: trunk/OpenMPT/src/mpt/base/detect_os.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/base/detect_os.hpp Mon May 20 21:01:14 2024 (r20832) +++ trunk/OpenMPT/src/mpt/base/detect_os.hpp Wed May 22 11:07:35 2024 (r20833) @@ -41,6 +41,7 @@ #define MPT_WIN_8 MPT_WIN_MAKE_VERSION(0x06, 0x02, 0x00, 0x00) #define MPT_WIN_81 MPT_WIN_MAKE_VERSION(0x06, 0x03, 0x00, 0x00) +#define MPT_WIN_10_PRE MPT_WIN_MAKE_VERSION(0x06, 0x04, 0x00, 0x00) #define MPT_WIN_10 MPT_WIN_MAKE_VERSION(0x0a, 0x00, 0x00, 0x00) // NTDDI_WIN10 1507 #define MPT_WIN_10_1511 MPT_WIN_MAKE_VERSION(0x0a, 0x00, 0x00, 0x01) // NTDDI_WIN10_TH2 1511 #define MPT_WIN_10_1607 MPT_WIN_MAKE_VERSION(0x0a, 0x00, 0x00, 0x02) // NTDDI_WIN10_RS1 1607 Modified: trunk/OpenMPT/src/mpt/osinfo/windows_version.hpp ============================================================================== --- trunk/OpenMPT/src/mpt/osinfo/windows_version.hpp Mon May 20 21:01:14 2024 (r20832) +++ trunk/OpenMPT/src/mpt/osinfo/windows_version.hpp Wed May 22 11:07:35 2024 (r20833) @@ -38,6 +38,7 @@ Win7 = 0x0000000600000001ull, Win8 = 0x0000000600000002ull, Win81 = 0x0000000600000003ull, + Win10Pre = 0x0000000600000004ull, Win10 = 0x0000000a00000000ull, WinNewer = Win10 + 1ull }; @@ -162,6 +163,8 @@ return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack(0, 0), 10586, 0); #elif MPT_WINNT_AT_LEAST(MPT_WIN_10) // 1507 return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win10, mpt::osinfo::windows::Version::ServicePack(0, 0), 10240, 0); +#elif MPT_WINNT_AT_LEAST(MPT_WIN_10_PRE) + return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win10Pre, mpt::osinfo::windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0, 0); #elif MPT_WINNT_AT_LEAST(MPT_WIN_81) return mpt::osinfo::windows::Version(mpt::osinfo::windows::Version::Win81, mpt::osinfo::windows::Version::ServicePack(((NTDDI_VERSION & 0xffffu) >> 8) & 0xffu, ((NTDDI_VERSION & 0xffffu) >> 0) & 0xffu), 0, 0); #elif MPT_WINNT_AT_LEAST(MPT_WIN_8) |
|
From: <sv...@op...> - 2024-05-20 19:01:22
|
Author: sagamusix Date: Mon May 20 21:01:14 2024 New Revision: 20832 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20832 Log: [Fix] Tentative fix for GetLength calculations with kITEmptyNoteMapSlotIgnoreCell. This code should be de-duplicated. Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp Modified: trunk/OpenMPT/soundlib/Snd_fx.cpp ============================================================================== --- trunk/OpenMPT/soundlib/Snd_fx.cpp Mon May 20 20:50:15 2024 (r20831) +++ trunk/OpenMPT/soundlib/Snd_fx.cpp Mon May 20 21:01:14 2024 (r20832) @@ -5,7 +5,7 @@ * Notes : This needs some heavy refactoring. * I thought of actually adding an effect interface class. Every pattern effect * could then be moved into its own class that inherits from the effect interface. - * If effect handling differs severly between module formats, every format would have + * If effect handling differs severely between module formats, every format would have * its own class for that effect. Then, a call chain of effect classes could be set up * for each format, since effects cannot be processed in the same order in all formats. * Authors: Olivier Lapicque @@ -22,7 +22,7 @@ #endif // MODPLUG_TRACKER #include "tuning.h" #include "Tables.h" -#include "modsmp_ctrl.h" // For updating the loop wraparound data with the invert loop effect +#include "modsmp_ctrl.h" // For updating the loop wraparound data with the invert loop effect #include "plugins/PlugInterface.h" #include "OPL.h" #include "MIDIEvents.h" @@ -520,6 +520,25 @@ chn.rowCommand.Clear(); continue; } + + if(p->IsNote()) + chn.nNewNote = chn.nLastNote = p->note; + else if(p->note > NOTE_MAX && m_playBehaviour[kITClearOldNoteAfterCut]) + chn.nNewNote = NOTE_NONE; + + if(m_playBehaviour[kITEmptyNoteMapSlotIgnoreCell] && p->instr > 0 && p->instr <= GetNumInstruments() + && Instruments[p->instr] != nullptr && !Instruments[p->instr]->HasValidMIDIChannel()) + { + auto note = (chn.rowCommand.note != NOTE_NONE) ? p->note : chn.nNewNote; + if (ModCommand::IsNote(note) && Instruments[p->instr]->Keyboard[note - NOTE_MIN] == 0) + { + chn.nNewNote = chn.nLastNote = note; + chn.nNewIns = static_cast<ModCommand::INSTR>(p->instr); + chn.rowCommand.Clear(); + continue; + } + } + chn.rowCommand = *p; switch(p->command) { @@ -589,12 +608,10 @@ if(chn.rowCommand.instr) { chn.nNewIns = chn.rowCommand.instr; - chn.nLastNote = NOTE_NONE; memory.chnSettings[nChn].vol = 0xFF; } if(chn.rowCommand.IsNote()) { - chn.nLastNote = note; chn.RestorePanAndFilter(); if(!adjustSamplePos || memory.chnSettings[nChn].ticksToRender == GetLengthMemory::IGNORE_CHANNEL) @@ -1035,7 +1052,6 @@ chn.increment = GetChannelIncrement(chn, chn.nPeriod, 0).first; } int32 setPan = chn.nPan; - chn.nNewNote = chn.nLastNote; if(chn.nNewIns != 0) InstrumentChange(chn, chn.nNewIns, porta); NoteChange(chn, m.note, porta); HandleNoteChangeFilter(chn); @@ -1286,10 +1302,6 @@ for(CHANNELINDEX n = 0; n < GetNumChannels(); n++) { auto &chn = m_PlayState.Chn[n]; - if(chn.nLastNote != NOTE_NONE) - { - chn.nNewNote = chn.nLastNote; - } if(memory.chnSettings[n].vol != 0xFF && !adjustSamplePos) { chn.nVolume = std::min(memory.chnSettings[n].vol, uint8(64)) * 4; @@ -1434,7 +1446,7 @@ // but still uses the sample info from the old one (bug?) returnAfterVolumeAdjust = true; } - // IT compatbility: Reset filter if portamento results in sample change + // IT compatibility: Reset filter if portamento results in sample change // Test case: FilterPortaSmpChange.it, FilterPortaSmpChange-InsMode.it if(m_playBehaviour[kITResetFilterOnPortaSmpChange] && !m_nInstruments) chn.triggerNote = true; @@ -2527,7 +2539,7 @@ // To achieve this, clearing the note data so that rest of the process sees the row as empty row. if(ModCommand::IsPcNote(chn.rowCommand.note)) { - chn.ClearRowCmd(); + chn.rowCommand.Clear(); instr = 0; volcmd = VOLCMD_NONE; vol = 0; @@ -2549,7 +2561,7 @@ { chn.nNewNote = chn.nLastNote = note; chn.nNewIns = static_cast<ModCommand::INSTR>(instr); - chn.ClearRowCmd(); + chn.rowCommand.Clear(); continue; } } @@ -2757,7 +2769,7 @@ note = NOTE_NONE; instr = 0; retrigEnv = false; - // FT2 Compatbility: Start fading the note for notes with no delay. Only relevant when a volume command is encountered after the note-off. + // FT2 Compatibility: Start fading the note for notes with no delay. Only relevant when a volume command is encountered after the note-off. // Test case: NoteOffFadeNoEnv.xm if(m_PlayState.m_flags[SONG_FIRSTTICK] && m_playBehaviour[kFT2NoteOffFlags]) chn.dwFlags.set(CHN_NOTEFADE); @@ -2879,7 +2891,7 @@ chn.nAutoVibDepth = 0; chn.nAutoVibPos = 0; chn.nFadeOutVol = 65536; - // FT2 Compatbility: Reset key-off status with instrument number + // FT2 Compatibility: Reset key-off status with instrument number // Test case: NoteOffInstrChange.xm if(m_playBehaviour[kFT2NoteOffFlags]) chn.dwFlags.reset(CHN_KEYOFF); |
|
From: <sv...@op...> - 2024-05-20 18:50:28
|
Author: sagamusix Date: Mon May 20 20:50:15 2024 New Revision: 20831 URL: https://source.openmpt.org/browse/openmpt/?op=revision&rev=20831 Log: [Ref] Modernize EffectWriter. Modified: trunk/OpenMPT/soundlib/pattern.h Modified: trunk/OpenMPT/soundlib/pattern.h ============================================================================== --- trunk/OpenMPT/soundlib/pattern.h Tue May 14 22:59:34 2024 (r20830) +++ trunk/OpenMPT/soundlib/pattern.h Mon May 20 20:50:15 2024 (r20831) @@ -150,7 +150,7 @@ friend class CPattern; // Row advance mode - enum RetryMode + enum RetryMode : uint8 { rmIgnore, // If effect can't be written, abort. rmTryNextRow, // If effect can't be written, try next row. @@ -159,8 +159,8 @@ public: // Constructors with effect commands - EffectWriter(EffectCommand cmd, ModCommand::PARAM param) : m_command(cmd), m_param(param), m_isVolEffect(false) { Init(); } - EffectWriter(VolumeCommand cmd, ModCommand::VOL param) : m_volcmd(cmd), m_vol(param), m_isVolEffect(true) { Init(); } + EffectWriter(EffectCommand cmd, ModCommand::PARAM param) : m_command(cmd), m_param(param), m_isVolEffect(false) { } + EffectWriter(VolumeCommand cmd, ModCommand::VOL param) : m_volcmd(cmd), m_vol(param), m_isVolEffect(true) { } // Additional constructors: // Set row in which writing should start @@ -174,9 +174,9 @@ EffectWriter &RetryPreviousRow() { m_retryMode = rmTryPreviousRow; return *this; } protected: - RetryMode m_retryMode; - ROWINDEX m_row; - CHANNELINDEX m_channel; + ROWINDEX m_row = 0; + CHANNELINDEX m_channel = CHANNELINDEX_INVALID; // Any channel by default + RetryMode m_retryMode = rmIgnore; union { @@ -189,19 +189,9 @@ ModCommand::VOL m_vol; }; - bool m_retry : 1; - bool m_allowMultiple : 1; - bool m_isVolEffect : 1; - - // Common data initialisation - void Init() - { - m_row = 0; - m_channel = CHANNELINDEX_INVALID; // Any channel - m_retryMode = rmIgnore; // If effect couldn't be written, abort. - m_retry = true; - m_allowMultiple = false; // Stop if same type of effect is encountered - } + bool m_retry = true; + bool m_allowMultiple = true; + bool m_isVolEffect = false; }; |