Loaders.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. /*
  2. * Loaders.h
  3. * ---------
  4. * Purpose: Common functions for module loaders
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "../common/misc_util.h"
  12. #include "../common/FileReader.h"
  13. #include "Sndfile.h"
  14. #include "SampleIO.h"
  15. OPENMPT_NAMESPACE_BEGIN
  16. // Functions to create 4-byte and 2-byte magic byte identifiers in little-endian format
  17. // Use this together with uint32le/uint16le file members.
  18. constexpr uint32 MagicLE(const char(&id)[5])
  19. {
  20. return static_cast<uint32>((static_cast<uint8>(id[3]) << 24) | (static_cast<uint8>(id[2]) << 16) | (static_cast<uint8>(id[1]) << 8) | static_cast<uint8>(id[0]));
  21. }
  22. constexpr uint16 MagicLE(const char(&id)[3])
  23. {
  24. return static_cast<uint16>((static_cast<uint8>(id[1]) << 8) | static_cast<uint8>(id[0]));
  25. }
  26. // Functions to create 4-byte and 2-byte magic byte identifiers in big-endian format
  27. // Use this together with uint32be/uint16be file members.
  28. // Note: Historically, some magic bytes in MPT-specific fields are reversed (due to the use of multi-char literals).
  29. // Such fields turned up reversed in files, so MagicBE is used to keep them readable in the code.
  30. constexpr uint32 MagicBE(const char(&id)[5])
  31. {
  32. return static_cast<uint32>((static_cast<uint8>(id[0]) << 24) | (static_cast<uint8>(id[1]) << 16) | (static_cast<uint8>(id[2]) << 8) | static_cast<uint8>(id[3]));
  33. }
  34. constexpr uint16 MagicBE(const char(&id)[3])
  35. {
  36. return static_cast<uint16>((static_cast<uint8>(id[0]) << 8) | static_cast<uint8>(id[1]));
  37. }
  38. // Read 'howMany' order items from an array.
  39. // 'stopIndex' is treated as '---', 'ignoreIndex' is treated as '+++'. If the format doesn't support such indices, just pass uint16_max.
  40. template<typename T, size_t arraySize>
  41. bool ReadOrderFromArray(ModSequence &order, const T(&orders)[arraySize], size_t howMany = arraySize, uint16 stopIndex = uint16_max, uint16 ignoreIndex = uint16_max)
  42. {
  43. static_assert(mpt::is_binary_safe<T>::value);
  44. LimitMax(howMany, arraySize);
  45. LimitMax(howMany, MAX_ORDERS);
  46. ORDERINDEX readEntries = static_cast<ORDERINDEX>(howMany);
  47. order.resize(readEntries);
  48. for(int i = 0; i < readEntries; i++)
  49. {
  50. PATTERNINDEX pat = static_cast<PATTERNINDEX>(orders[i]);
  51. if(pat == stopIndex) pat = order.GetInvalidPatIndex();
  52. else if(pat == ignoreIndex) pat = order.GetIgnoreIndex();
  53. order.at(i) = pat;
  54. }
  55. return true;
  56. }
  57. // Read 'howMany' order items as integers with defined endianness from a file.
  58. // 'stopIndex' is treated as '---', 'ignoreIndex' is treated as '+++'. If the format doesn't support such indices, just pass uint16_max.
  59. template<typename T>
  60. bool ReadOrderFromFile(ModSequence &order, FileReader &file, size_t howMany, uint16 stopIndex = uint16_max, uint16 ignoreIndex = uint16_max)
  61. {
  62. static_assert(mpt::is_binary_safe<T>::value);
  63. if(!file.CanRead(howMany * sizeof(T)))
  64. return false;
  65. LimitMax(howMany, MAX_ORDERS);
  66. ORDERINDEX readEntries = static_cast<ORDERINDEX>(howMany);
  67. order.resize(readEntries);
  68. T patF;
  69. for(auto &pat : order)
  70. {
  71. file.ReadStruct(patF);
  72. pat = static_cast<PATTERNINDEX>(patF);
  73. if(pat == stopIndex) pat = order.GetInvalidPatIndex();
  74. else if(pat == ignoreIndex) pat = order.GetIgnoreIndex();
  75. }
  76. return true;
  77. }
  78. OPENMPT_NAMESPACE_END