Load_uax.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Load_uax.cpp
  3. * ------------
  4. * Purpose: UAX (Unreal Sounds) module ripper
  5. * Notes : The sounds are read into module sample slots.
  6. * Authors: Johannes Schultz (inspired by code from http://wiki.beyondunreal.com/Legacy:Package_File_Format)
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #include "stdafx.h"
  10. #include "Loaders.h"
  11. #include "UMXTools.h"
  12. OPENMPT_NAMESPACE_BEGIN
  13. CSoundFile::ProbeResult CSoundFile::ProbeFileHeaderUAX(MemoryFileReader file, const uint64 *pfilesize)
  14. {
  15. return UMX::ProbeFileHeader(file, pfilesize, "sound");
  16. }
  17. bool CSoundFile::ReadUAX(FileReader &file, ModLoadingFlags loadFlags)
  18. {
  19. file.Rewind();
  20. UMX::FileHeader fileHeader;
  21. if(!file.ReadStruct(fileHeader) || !fileHeader.IsValid())
  22. return false;
  23. // Note that this can be a false positive, e.g. Unreal maps will have music and sound
  24. // in their name table because they usually import such files. However, it spares us
  25. // from wildly seeking through the file, as the name table is usually right at the
  26. // start of the file, so it is hopefully a good enough heuristic for our purposes.
  27. if(!UMX::FindNameTableEntry(file, fileHeader, "sound"))
  28. return false;
  29. else if(!file.CanRead(fileHeader.GetMinimumAdditionalFileSize()))
  30. return false;
  31. else if(loadFlags == onlyVerifyHeader)
  32. return true;
  33. const std::vector<std::string> names = UMX::ReadNameTable(file, fileHeader);
  34. const std::vector<int32> classes = UMX::ReadImportTable(file, fileHeader, names);
  35. InitializeGlobals();
  36. m_modFormat.formatName = MPT_UFORMAT("Unreal Package v{}")(fileHeader.packageVersion);
  37. m_modFormat.type = U_("uax");
  38. m_modFormat.charset = mpt::Charset::Windows1252;
  39. // Read export table
  40. file.Seek(fileHeader.exportOffset);
  41. for(uint32 i = 0; i < fileHeader.exportCount && file.CanRead(8); i++)
  42. {
  43. auto [fileChunk, objName] = UMX::ReadExportTableEntry(file, fileHeader, classes, names, "sound");
  44. if(!fileChunk.IsValid())
  45. continue;
  46. if(CanAddMoreSamples())
  47. {
  48. // Read as sample
  49. if(ReadSampleFromFile(GetNumSamples() + 1, fileChunk, true))
  50. {
  51. if(objName > 0 && static_cast<size_t>(objName) < names.size())
  52. {
  53. m_szNames[GetNumSamples()] = names[objName];
  54. }
  55. }
  56. }
  57. }
  58. if(m_nSamples != 0)
  59. {
  60. InitializeChannels();
  61. SetType(MOD_TYPE_MPT);
  62. m_ContainerType = MOD_CONTAINERTYPE_UAX;
  63. m_nChannels = 4;
  64. Patterns.Insert(0, 64);
  65. Order().assign(1, 0);
  66. return true;
  67. } else
  68. {
  69. return false;
  70. }
  71. }
  72. OPENMPT_NAMESPACE_END