1
0

Load_stp.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. /*
  2. * Load_stp.cpp
  3. * ------------
  4. * Purpose: STP (Soundtracker Pro II) module loader
  5. * Notes : A few exotic effects aren't supported.
  6. * Multiple sample loops are supported, but only the first 10 can be used as cue points
  7. * (with 16xx and 18xx).
  8. * Fractional speed values and combined auto effects are handled whenever possible,
  9. * but some effects may be omitted (and there may be tempo accuracy issues).
  10. * Authors: Devin Acker
  11. * OpenMPT Devs
  12. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  13. *
  14. * Wisdom from the Soundtracker Pro II manual:
  15. * "To create shorter patterns, simply create shorter patterns."
  16. */
  17. #include "stdafx.h"
  18. #include "Loaders.h"
  19. OPENMPT_NAMESPACE_BEGIN
  20. // File header
  21. struct STPFileHeader
  22. {
  23. char magic[4];
  24. uint16be version;
  25. uint8be numOrders;
  26. uint8be patternLength;
  27. uint8be orderList[128];
  28. uint16be speed;
  29. uint16be speedFrac;
  30. uint16be timerCount;
  31. uint16be flags;
  32. uint32be reserved;
  33. uint16be midiCount; // always 50
  34. uint8be midi[50];
  35. uint16be numSamples;
  36. uint16be sampleStructSize;
  37. };
  38. MPT_BINARY_STRUCT(STPFileHeader, 204)
  39. // Sample header (common part between all versions)
  40. struct STPSampleHeader
  41. {
  42. uint32be length;
  43. uint8be volume;
  44. uint8be reserved1;
  45. uint32be loopStart;
  46. uint32be loopLength;
  47. uint16be defaultCommand; // Default command to put next to note when editing patterns; not relevant for playback
  48. // The following 4 bytes are reserved in version 0 and 1.
  49. uint16be defaultPeriod;
  50. uint8be finetune;
  51. uint8be reserved2;
  52. void ConvertToMPT(ModSample &mptSmp) const
  53. {
  54. mptSmp.nLength = length;
  55. mptSmp.nVolume = 4u * std::min(volume.get(), uint8(64));
  56. mptSmp.nLoopStart = loopStart;
  57. mptSmp.nLoopEnd = loopStart + loopLength;
  58. if(mptSmp.nLoopStart >= mptSmp.nLength)
  59. {
  60. mptSmp.nLoopStart = mptSmp.nLength - 1;
  61. }
  62. if(mptSmp.nLoopEnd > mptSmp.nLength)
  63. {
  64. mptSmp.nLoopEnd = mptSmp.nLength;
  65. }
  66. if(mptSmp.nLoopStart > mptSmp.nLoopEnd)
  67. {
  68. mptSmp.nLoopStart = 0;
  69. mptSmp.nLoopEnd = 0;
  70. } else if(mptSmp.nLoopEnd > mptSmp.nLoopStart)
  71. {
  72. mptSmp.uFlags.set(CHN_LOOP);
  73. mptSmp.cues[0] = mptSmp.nLoopStart;
  74. }
  75. }
  76. };
  77. MPT_BINARY_STRUCT(STPSampleHeader, 20)
  78. struct STPLoopInfo
  79. {
  80. SmpLength loopStart;
  81. SmpLength loopLength;
  82. SAMPLEINDEX looped;
  83. SAMPLEINDEX nonLooped;
  84. };
  85. typedef std::vector<STPLoopInfo> STPLoopList;
  86. static TEMPO ConvertTempo(uint16 ciaSpeed)
  87. {
  88. // 3546 is the resulting CIA timer value when using 4F7D (tempo 125 bpm) command in STProII
  89. return TEMPO((125.0 * 3546.0) / ciaSpeed);
  90. }
  91. static void ConvertLoopSlice(ModSample &src, ModSample &dest, SmpLength start, SmpLength len, bool loop)
  92. {
  93. if(!src.HasSampleData()
  94. || start >= src.nLength
  95. || src.nLength - start < len)
  96. {
  97. return;
  98. }
  99. dest.FreeSample();
  100. dest = src;
  101. dest.nLength = len;
  102. dest.pData.pSample = nullptr;
  103. if(!dest.AllocateSample())
  104. {
  105. return;
  106. }
  107. // only preserve cue points if the target sample length is the same
  108. if(len != src.nLength)
  109. MemsetZero(dest.cues);
  110. std::memcpy(dest.sampleb(), src.sampleb() + start, len);
  111. dest.uFlags.set(CHN_LOOP, loop);
  112. if(loop)
  113. {
  114. dest.nLoopStart = 0;
  115. dest.nLoopEnd = len;
  116. } else
  117. {
  118. dest.nLoopStart = 0;
  119. dest.nLoopEnd = 0;
  120. }
  121. }
  122. static void ConvertLoopSequence(ModSample &smp, STPLoopList &loopList)
  123. {
  124. // This should only modify a sample if it has more than one loop
  125. // (otherwise, it behaves like a normal sample loop)
  126. if(!smp.HasSampleData() || loopList.size() < 2) return;
  127. ModSample newSmp = smp;
  128. newSmp.nLength = 0;
  129. newSmp.pData.pSample = nullptr;
  130. size_t numLoops = loopList.size();
  131. // Get the total length of the sample after combining all looped sections
  132. for(size_t i = 0; i < numLoops; i++)
  133. {
  134. STPLoopInfo &info = loopList[i];
  135. // If adding this loop would cause the sample length to exceed maximum,
  136. // then limit and bail out
  137. if(info.loopStart >= smp.nLength
  138. || smp.nLength - info.loopStart < info.loopLength
  139. || newSmp.nLength > MAX_SAMPLE_LENGTH - info.loopLength)
  140. {
  141. numLoops = i;
  142. break;
  143. }
  144. newSmp.nLength += info.loopLength;
  145. }
  146. if(!newSmp.AllocateSample())
  147. {
  148. return;
  149. }
  150. // start copying the looped sample data parts
  151. SmpLength start = 0;
  152. for(size_t i = 0; i < numLoops; i++)
  153. {
  154. STPLoopInfo &info = loopList[i];
  155. memcpy(newSmp.sampleb() + start, smp.sampleb() + info.loopStart, info.loopLength);
  156. // update loop info based on position in edited sample
  157. info.loopStart = start;
  158. if(i > 0 && i <= std::size(newSmp.cues))
  159. {
  160. newSmp.cues[i - 1] = start;
  161. }
  162. start += info.loopLength;
  163. }
  164. // replace old sample with new one
  165. smp.FreeSample();
  166. smp = newSmp;
  167. smp.nLoopStart = 0;
  168. smp.nLoopEnd = smp.nLength;
  169. smp.uFlags.set(CHN_LOOP);
  170. }
  171. static bool ValidateHeader(const STPFileHeader &fileHeader)
  172. {
  173. if(std::memcmp(fileHeader.magic, "STP3", 4)
  174. || fileHeader.version > 2
  175. || fileHeader.numOrders > 128
  176. || fileHeader.numSamples >= MAX_SAMPLES
  177. || fileHeader.timerCount == 0
  178. || fileHeader.midiCount != 50)
  179. {
  180. return false;
  181. }
  182. return true;
  183. }
  184. CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderSTP(MemoryFileReader file, const uint64 *pfilesize)
  185. {
  186. STPFileHeader fileHeader;
  187. if(!file.ReadStruct(fileHeader))
  188. {
  189. return ProbeWantMoreData;
  190. }
  191. if(!ValidateHeader(fileHeader))
  192. {
  193. return ProbeFailure;
  194. }
  195. MPT_UNREFERENCED_PARAMETER(pfilesize);
  196. return ProbeSuccess;
  197. }
  198. bool CSoundFile::ReadSTP(FileReader &file, ModLoadingFlags loadFlags)
  199. {
  200. file.Rewind();
  201. STPFileHeader fileHeader;
  202. if(!file.ReadStruct(fileHeader))
  203. {
  204. return false;
  205. }
  206. if(!ValidateHeader(fileHeader))
  207. {
  208. return false;
  209. }
  210. if(loadFlags == onlyVerifyHeader)
  211. {
  212. return true;
  213. }
  214. InitializeGlobals(MOD_TYPE_STP);
  215. m_modFormat.formatName = MPT_UFORMAT("Soundtracker Pro II v{}")(fileHeader.version);
  216. m_modFormat.type = U_("stp");
  217. m_modFormat.charset = mpt::Charset::Amiga_no_C1;
  218. m_nChannels = 4;
  219. m_nSamples = 0;
  220. m_nDefaultSpeed = fileHeader.speed;
  221. m_nDefaultTempo = ConvertTempo(fileHeader.timerCount);
  222. m_nMinPeriod = 14 * 4;
  223. m_nMaxPeriod = 3424 * 4;
  224. ReadOrderFromArray(Order(), fileHeader.orderList, fileHeader.numOrders);
  225. std::vector<STPLoopList> loopInfo;
  226. // Non-looped versions of samples with loops (when needed)
  227. std::vector<SAMPLEINDEX> nonLooped;
  228. // Load sample headers
  229. SAMPLEINDEX samplesInFile = 0;
  230. for(SAMPLEINDEX smp = 0; smp < fileHeader.numSamples; smp++)
  231. {
  232. SAMPLEINDEX actualSmp = file.ReadUint16BE();
  233. if(actualSmp == 0 || actualSmp >= MAX_SAMPLES)
  234. return false;
  235. uint32 chunkSize = fileHeader.sampleStructSize;
  236. if(fileHeader.version == 2)
  237. chunkSize = file.ReadUint32BE() - 2;
  238. FileReader chunk = file.ReadChunk(chunkSize);
  239. samplesInFile = m_nSamples = std::max(m_nSamples, actualSmp);
  240. ModSample &mptSmp = Samples[actualSmp];
  241. mptSmp.Initialize(MOD_TYPE_MOD);
  242. if(fileHeader.version < 2)
  243. {
  244. // Read path
  245. chunk.ReadString<mpt::String::maybeNullTerminated>(mptSmp.filename, 31);
  246. // Ignore flags, they are all not relevant for us
  247. chunk.Skip(1);
  248. // Read filename / sample text
  249. chunk.ReadString<mpt::String::maybeNullTerminated>(m_szNames[actualSmp], 30);
  250. } else
  251. {
  252. std::string str;
  253. // Read path
  254. chunk.ReadNullString(str, 257);
  255. mptSmp.filename = str;
  256. // Ignore flags, they are all not relevant for us
  257. chunk.Skip(1);
  258. // Read filename / sample text
  259. chunk.ReadNullString(str, 31);
  260. m_szNames[actualSmp] = str;
  261. // Seek to even boundary
  262. if(chunk.GetPosition() % 2u)
  263. chunk.Skip(1);
  264. }
  265. STPSampleHeader sampleHeader;
  266. chunk.ReadStruct(sampleHeader);
  267. sampleHeader.ConvertToMPT(mptSmp);
  268. if(fileHeader.version == 2)
  269. {
  270. mptSmp.nFineTune = static_cast<int8>(sampleHeader.finetune << 3);
  271. }
  272. if(fileHeader.version >= 1)
  273. {
  274. nonLooped.resize(samplesInFile);
  275. loopInfo.resize(samplesInFile);
  276. STPLoopList &loopList = loopInfo[actualSmp - 1];
  277. loopList.clear();
  278. const uint16 numLoops = file.ReadUint16BE();
  279. if(!file.CanRead(numLoops * 8u))
  280. return false;
  281. loopList.reserve(numLoops);
  282. STPLoopInfo loop;
  283. loop.looped = loop.nonLooped = 0;
  284. if(numLoops == 0 && mptSmp.uFlags[CHN_LOOP])
  285. {
  286. loop.loopStart = mptSmp.nLoopStart;
  287. loop.loopLength = mptSmp.nLoopEnd - mptSmp.nLoopStart;
  288. loopList.push_back(loop);
  289. } else for(uint16 i = 0; i < numLoops; i++)
  290. {
  291. loop.loopStart = file.ReadUint32BE();
  292. loop.loopLength = file.ReadUint32BE();
  293. loopList.push_back(loop);
  294. }
  295. }
  296. }
  297. // Load patterns
  298. uint16 numPatterns = 128;
  299. if(fileHeader.version == 0)
  300. numPatterns = file.ReadUint16BE();
  301. uint16 patternLength = fileHeader.patternLength;
  302. CHANNELINDEX channels = 4;
  303. if(fileHeader.version > 0)
  304. {
  305. // Scan for total number of channels
  306. FileReader::off_t patOffset = file.GetPosition();
  307. for(uint16 pat = 0; pat < numPatterns; pat++)
  308. {
  309. PATTERNINDEX actualPat = file.ReadUint16BE();
  310. if(actualPat == 0xFFFF)
  311. break;
  312. patternLength = file.ReadUint16BE();
  313. channels = file.ReadUint16BE();
  314. if(channels > MAX_BASECHANNELS)
  315. return false;
  316. m_nChannels = std::max(m_nChannels, channels);
  317. file.Skip(channels * patternLength * 4u);
  318. }
  319. file.Seek(patOffset);
  320. }
  321. struct ChannelMemory
  322. {
  323. uint8 autoFinePorta, autoPortaUp, autoPortaDown, autoVolSlide, autoVibrato;
  324. uint8 vibratoMem, autoTremolo, autoTonePorta, tonePortaMem;
  325. };
  326. std::vector<ChannelMemory> channelMemory(m_nChannels);
  327. uint8 globalVolSlide = 0;
  328. uint8 speedFrac = static_cast<uint8>(fileHeader.speedFrac);
  329. for(uint16 pat = 0; pat < numPatterns; pat++)
  330. {
  331. PATTERNINDEX actualPat = pat;
  332. if(fileHeader.version > 0)
  333. {
  334. actualPat = file.ReadUint16BE();
  335. if(actualPat == 0xFFFF)
  336. break;
  337. patternLength = file.ReadUint16BE();
  338. channels = file.ReadUint16BE();
  339. }
  340. if(!file.CanRead(channels * patternLength * 4u))
  341. break;
  342. if(!(loadFlags & loadPatternData) || !Patterns.Insert(actualPat, patternLength))
  343. {
  344. file.Skip(channels * patternLength * 4u);
  345. continue;
  346. }
  347. for(ROWINDEX row = 0; row < patternLength; row++)
  348. {
  349. auto rowBase = Patterns[actualPat].GetRow(row);
  350. bool didGlobalVolSlide = false;
  351. // if a fractional speed value is in use then determine if we should stick a fine pattern delay somewhere
  352. bool shouldDelay;
  353. switch(speedFrac & 3)
  354. {
  355. default: shouldDelay = false; break;
  356. // 1/4
  357. case 1: shouldDelay = (row & 3) == 0; break;
  358. // 1/2
  359. case 2: shouldDelay = (row & 1) == 0; break;
  360. // 3/4
  361. case 3: shouldDelay = (row & 3) != 3; break;
  362. }
  363. for(CHANNELINDEX chn = 0; chn < channels; chn++)
  364. {
  365. ChannelMemory &chnMem = channelMemory[chn];
  366. ModCommand &m = rowBase[chn];
  367. const auto [instr, note, command, param] = file.ReadArray<uint8, 4>();
  368. m.instr = instr;
  369. m.note = note;
  370. m.param = param;
  371. if(m.note)
  372. {
  373. m.note += 24 + NOTE_MIN;
  374. chnMem = ChannelMemory();
  375. }
  376. // this is a nibble-swapped param value used for auto fine volside
  377. // and auto global fine volside
  378. uint8 swapped = (m.param >> 4) | (m.param << 4);
  379. if((command & 0xF0) == 0xF0)
  380. {
  381. // 12-bit CIA tempo
  382. uint16 ciaTempo = (static_cast<uint16>(command & 0x0F) << 8) | m.param;
  383. if(ciaTempo)
  384. {
  385. m.param = mpt::saturate_round<ModCommand::PARAM>(ConvertTempo(ciaTempo).ToDouble());
  386. m.command = CMD_TEMPO;
  387. } else
  388. {
  389. m.command = CMD_NONE;
  390. }
  391. } else switch(command)
  392. {
  393. case 0x00: // arpeggio
  394. if(m.param)
  395. m.command = CMD_ARPEGGIO;
  396. else
  397. m.command = CMD_NONE;
  398. break;
  399. case 0x01: // portamento up
  400. m.command = CMD_PORTAMENTOUP;
  401. break;
  402. case 0x02: // portamento down
  403. m.command = CMD_PORTAMENTODOWN;
  404. break;
  405. case 0x03: // auto fine portamento up
  406. chnMem.autoFinePorta = 0x10 | std::min(m.param, ModCommand::PARAM(15));
  407. chnMem.autoPortaUp = 0;
  408. chnMem.autoPortaDown = 0;
  409. chnMem.autoTonePorta = 0;
  410. m.command = CMD_NONE;
  411. break;
  412. case 0x04: // auto fine portamento down
  413. chnMem.autoFinePorta = 0x20 | std::min(m.param, ModCommand::PARAM(15));
  414. chnMem.autoPortaUp = 0;
  415. chnMem.autoPortaDown = 0;
  416. chnMem.autoTonePorta = 0;
  417. m.command = CMD_NONE;
  418. break;
  419. case 0x05: // auto portamento up
  420. chnMem.autoFinePorta = 0;
  421. chnMem.autoPortaUp = m.param;
  422. chnMem.autoPortaDown = 0;
  423. chnMem.autoTonePorta = 0;
  424. m.command = CMD_NONE;
  425. break;
  426. case 0x06: // auto portamento down
  427. chnMem.autoFinePorta = 0;
  428. chnMem.autoPortaUp = 0;
  429. chnMem.autoPortaDown = m.param;
  430. chnMem.autoTonePorta = 0;
  431. m.command = CMD_NONE;
  432. break;
  433. case 0x07: // set global volume
  434. m.command = CMD_GLOBALVOLUME;
  435. globalVolSlide = 0;
  436. break;
  437. case 0x08: // auto global fine volume slide
  438. globalVolSlide = swapped;
  439. m.command = CMD_NONE;
  440. break;
  441. case 0x09: // fine portamento up
  442. m.command = CMD_MODCMDEX;
  443. m.param = 0x10 | std::min(m.param, ModCommand::PARAM(15));
  444. break;
  445. case 0x0A: // fine portamento down
  446. m.command = CMD_MODCMDEX;
  447. m.param = 0x20 | std::min(m.param, ModCommand::PARAM(15));
  448. break;
  449. case 0x0B: // auto fine volume slide
  450. chnMem.autoVolSlide = swapped;
  451. m.command = CMD_NONE;
  452. break;
  453. case 0x0C: // set volume
  454. m.volcmd = VOLCMD_VOLUME;
  455. m.vol = m.param;
  456. chnMem.autoVolSlide = 0;
  457. m.command = CMD_NONE;
  458. break;
  459. case 0x0D: // volume slide (param is swapped compared to .mod)
  460. if(m.param & 0xF0)
  461. {
  462. m.volcmd = VOLCMD_VOLSLIDEDOWN;
  463. m.vol = m.param >> 4;
  464. } else if(m.param & 0x0F)
  465. {
  466. m.volcmd = VOLCMD_VOLSLIDEUP;
  467. m.vol = m.param & 0xF;
  468. }
  469. chnMem.autoVolSlide = 0;
  470. m.command = CMD_NONE;
  471. break;
  472. case 0x0E: // set filter (also uses opposite value compared to .mod)
  473. m.command = CMD_MODCMDEX;
  474. m.param = 1 ^ (m.param ? 1 : 0);
  475. break;
  476. case 0x0F: // set speed
  477. m.command = CMD_SPEED;
  478. speedFrac = m.param & 0x0F;
  479. m.param >>= 4;
  480. break;
  481. case 0x10: // auto vibrato
  482. chnMem.autoVibrato = m.param;
  483. chnMem.vibratoMem = 0;
  484. m.command = CMD_NONE;
  485. break;
  486. case 0x11: // auto tremolo
  487. if(m.param & 0xF)
  488. chnMem.autoTremolo = m.param;
  489. else
  490. chnMem.autoTremolo = 0;
  491. m.command = CMD_NONE;
  492. break;
  493. case 0x12: // pattern break
  494. m.command = CMD_PATTERNBREAK;
  495. break;
  496. case 0x13: // auto tone portamento
  497. chnMem.autoFinePorta = 0;
  498. chnMem.autoPortaUp = 0;
  499. chnMem.autoPortaDown = 0;
  500. chnMem.autoTonePorta = m.param;
  501. chnMem.tonePortaMem = 0;
  502. m.command = CMD_NONE;
  503. break;
  504. case 0x14: // position jump
  505. m.command = CMD_POSITIONJUMP;
  506. break;
  507. case 0x16: // start loop sequence
  508. if(m.instr && m.instr <= loopInfo.size())
  509. {
  510. STPLoopList &loopList = loopInfo[m.instr - 1];
  511. m.param--;
  512. if(m.param < std::min(std::size(ModSample().cues), loopList.size()))
  513. {
  514. m.volcmd = VOLCMD_OFFSET;
  515. m.vol = m.param;
  516. }
  517. }
  518. m.command = CMD_NONE;
  519. break;
  520. case 0x17: // play only loop nn
  521. if(m.instr && m.instr <= loopInfo.size())
  522. {
  523. STPLoopList &loopList = loopInfo[m.instr - 1];
  524. m.param--;
  525. if(m.param < loopList.size())
  526. {
  527. if(!loopList[m.param].looped && CanAddMoreSamples())
  528. loopList[m.param].looped = ++m_nSamples;
  529. m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].looped);
  530. }
  531. }
  532. m.command = CMD_NONE;
  533. break;
  534. case 0x18: // play sequence without loop
  535. if(m.instr && m.instr <= loopInfo.size())
  536. {
  537. STPLoopList &loopList = loopInfo[m.instr - 1];
  538. m.param--;
  539. if(m.param < std::min(std::size(ModSample().cues), loopList.size()))
  540. {
  541. m.volcmd = VOLCMD_OFFSET;
  542. m.vol = m.param;
  543. }
  544. // switch to non-looped version of sample and create it if needed
  545. if(!nonLooped[m.instr - 1] && CanAddMoreSamples())
  546. nonLooped[m.instr - 1] = ++m_nSamples;
  547. m.instr = static_cast<ModCommand::INSTR>(nonLooped[m.instr - 1]);
  548. }
  549. m.command = CMD_NONE;
  550. break;
  551. case 0x19: // play only loop nn without loop
  552. if(m.instr && m.instr <= loopInfo.size())
  553. {
  554. STPLoopList &loopList = loopInfo[m.instr - 1];
  555. m.param--;
  556. if(m.param < loopList.size())
  557. {
  558. if(!loopList[m.param].nonLooped && CanAddMoreSamples())
  559. loopList[m.param].nonLooped = ++m_nSamples;
  560. m.instr = static_cast<ModCommand::INSTR>(loopList[m.param].nonLooped);
  561. }
  562. }
  563. m.command = CMD_NONE;
  564. break;
  565. case 0x1D: // fine volume slide (nibble order also swapped)
  566. m.command = CMD_VOLUMESLIDE;
  567. m.param = swapped;
  568. if(m.param & 0xF0) // slide down
  569. m.param |= 0x0F;
  570. else if(m.param & 0x0F)
  571. m.param |= 0xF0;
  572. break;
  573. case 0x20: // "delayed fade"
  574. // just behave like either a normal fade or a notecut
  575. // depending on the speed
  576. if(m.param & 0xF0)
  577. {
  578. chnMem.autoVolSlide = m.param >> 4;
  579. m.command = CMD_NONE;
  580. } else
  581. {
  582. m.command = CMD_MODCMDEX;
  583. m.param = 0xC0 | (m.param & 0xF);
  584. }
  585. break;
  586. case 0x21: // note delay
  587. m.command = CMD_MODCMDEX;
  588. m.param = 0xD0 | std::min(m.param, ModCommand::PARAM(15));
  589. break;
  590. case 0x22: // retrigger note
  591. m.command = CMD_MODCMDEX;
  592. m.param = 0x90 | std::min(m.param, ModCommand::PARAM(15));
  593. break;
  594. case 0x49: // set sample offset
  595. m.command = CMD_OFFSET;
  596. break;
  597. case 0x4E: // other protracker commands (pattern loop / delay)
  598. if((m.param & 0xF0) == 0x60 || (m.param & 0xF0) == 0xE0)
  599. m.command = CMD_MODCMDEX;
  600. else
  601. m.command = CMD_NONE;
  602. break;
  603. case 0x4F: // set speed/tempo
  604. if(m.param < 0x20)
  605. {
  606. m.command = CMD_SPEED;
  607. speedFrac = 0;
  608. } else
  609. {
  610. m.command = CMD_TEMPO;
  611. }
  612. break;
  613. default:
  614. m.command = CMD_NONE;
  615. break;
  616. }
  617. bool didVolSlide = false;
  618. // try to put volume slide in volume command
  619. if(chnMem.autoVolSlide && m.volcmd == VOLCMD_NONE)
  620. {
  621. if(chnMem.autoVolSlide & 0xF0)
  622. {
  623. m.volcmd = VOLCMD_FINEVOLUP;
  624. m.vol = chnMem.autoVolSlide >> 4;
  625. } else
  626. {
  627. m.volcmd = VOLCMD_FINEVOLDOWN;
  628. m.vol = chnMem.autoVolSlide & 0xF;
  629. }
  630. didVolSlide = true;
  631. }
  632. // try to place/combine all remaining running effects.
  633. if(m.command == CMD_NONE)
  634. {
  635. if(chnMem.autoPortaUp)
  636. {
  637. m.command = CMD_PORTAMENTOUP;
  638. m.param = chnMem.autoPortaUp;
  639. } else if(chnMem.autoPortaDown)
  640. {
  641. m.command = CMD_PORTAMENTODOWN;
  642. m.param = chnMem.autoPortaDown;
  643. } else if(chnMem.autoFinePorta)
  644. {
  645. m.command = CMD_MODCMDEX;
  646. m.param = chnMem.autoFinePorta;
  647. } else if(chnMem.autoTonePorta)
  648. {
  649. m.command = CMD_TONEPORTAMENTO;
  650. m.param = chnMem.tonePortaMem = chnMem.autoTonePorta;
  651. } else if(chnMem.autoVibrato)
  652. {
  653. m.command = CMD_VIBRATO;
  654. m.param = chnMem.vibratoMem = chnMem.autoVibrato;
  655. } else if(!didVolSlide && chnMem.autoVolSlide)
  656. {
  657. m.command = CMD_VOLUMESLIDE;
  658. m.param = chnMem.autoVolSlide;
  659. // convert to a "fine" value by setting the other nibble to 0xF
  660. if(m.param & 0x0F)
  661. m.param |= 0xF0;
  662. else if(m.param & 0xF0)
  663. m.param |= 0x0F;
  664. didVolSlide = true;
  665. MPT_UNUSED(didVolSlide);
  666. } else if(chnMem.autoTremolo)
  667. {
  668. m.command = CMD_TREMOLO;
  669. m.param = chnMem.autoTremolo;
  670. } else if(shouldDelay)
  671. {
  672. // insert a fine pattern delay here
  673. m.command = CMD_S3MCMDEX;
  674. m.param = 0x61;
  675. shouldDelay = false;
  676. } else if(!didGlobalVolSlide && globalVolSlide)
  677. {
  678. m.command = CMD_GLOBALVOLSLIDE;
  679. m.param = globalVolSlide;
  680. // convert to a "fine" value by setting the other nibble to 0xF
  681. if(m.param & 0x0F)
  682. m.param |= 0xF0;
  683. else if(m.param & 0xF0)
  684. m.param |= 0x0F;
  685. didGlobalVolSlide = true;
  686. }
  687. }
  688. }
  689. // TODO: create/use extra channels for global volslide/delay if needed
  690. }
  691. }
  692. // after we know how many channels there really are...
  693. m_nSamplePreAmp = 256 / m_nChannels;
  694. // Setup channel pan positions and volume
  695. SetupMODPanning(true);
  696. // Skip over scripts and drumpad info
  697. if(fileHeader.version > 0)
  698. {
  699. while(file.CanRead(2))
  700. {
  701. uint16 scriptNum = file.ReadUint16BE();
  702. if(scriptNum == 0xFFFF)
  703. break;
  704. file.Skip(2);
  705. uint32 length = file.ReadUint32BE();
  706. file.Skip(length);
  707. }
  708. // Skip drumpad stuff
  709. file.Skip(17 * 2);
  710. }
  711. // Reading samples
  712. if(loadFlags & loadSampleData)
  713. {
  714. for(SAMPLEINDEX smp = 1; smp <= samplesInFile; smp++) if(Samples[smp].nLength)
  715. {
  716. SampleIO(
  717. SampleIO::_8bit,
  718. SampleIO::mono,
  719. SampleIO::littleEndian,
  720. SampleIO::signedPCM)
  721. .ReadSample(Samples[smp], file);
  722. if(smp > loopInfo.size())
  723. continue;
  724. ConvertLoopSequence(Samples[smp], loopInfo[smp - 1]);
  725. // make a non-looping duplicate of this sample if needed
  726. if(nonLooped[smp - 1])
  727. {
  728. ConvertLoopSlice(Samples[smp], Samples[nonLooped[smp - 1]], 0, Samples[smp].nLength, false);
  729. }
  730. for(const auto &info : loopInfo[smp - 1])
  731. {
  732. // make duplicate samples for this individual section if needed
  733. if(info.looped)
  734. {
  735. ConvertLoopSlice(Samples[smp], Samples[info.looped], info.loopStart, info.loopLength, true);
  736. }
  737. if(info.nonLooped)
  738. {
  739. ConvertLoopSlice(Samples[smp], Samples[info.nonLooped], info.loopStart, info.loopLength, false);
  740. }
  741. }
  742. }
  743. }
  744. return true;
  745. }
  746. OPENMPT_NAMESPACE_END