CPkgReader.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #include <WallpaperEngine/Irrlicht/Irrlicht.h>
  2. #include "CPkgReader.h"
  3. using namespace WallpaperEngine::Irrlicht;
  4. CArchiveLoaderPkg::CArchiveLoaderPkg(irr::io::IFileSystem* fs)
  5. : FileSystem(fs)
  6. {
  7. #ifdef _DEBUG
  8. setDebugName("CArchiveLoaderWAD");
  9. #endif
  10. }
  11. //! returns true if the file maybe is able to be loaded by this class
  12. bool CArchiveLoaderPkg::isALoadableFileFormat(const irr::io::path& filename) const
  13. {
  14. return irr::core::hasFileExtension (filename, "pkg");
  15. }
  16. //! Creates an archive from the filename
  17. /** \param file File handle to check.
  18. \return Pointer to newly created archive, or 0 upon error. */
  19. irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(const irr::io::path& filename, bool ignoreCase, bool ignorePaths) const
  20. {
  21. irr::io::IFileArchive *archive = nullptr;
  22. irr::io::IReadFile* file = FileSystem->createAndOpenFile(filename);
  23. if (file)
  24. {
  25. archive = createArchive (file, ignoreCase, ignorePaths);
  26. file->drop ();
  27. }
  28. return archive;
  29. }
  30. //! creates/loads an archive from the file.
  31. //! \return Pointer to the created archive. Returns 0 if loading failed.
  32. irr::io::IFileArchive* CArchiveLoaderPkg::createArchive(irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths) const
  33. {
  34. irr::io::IFileArchive *archive = nullptr;
  35. if (file)
  36. {
  37. file->seek (0);
  38. archive = new CPkgReader (file, ignoreCase, ignorePaths);
  39. }
  40. return archive;
  41. }
  42. //! Check if the file might be loaded by this class
  43. /** Check might look into the file.
  44. \param file File handle to check.
  45. \return True if file seems to be loadable. */
  46. bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::IReadFile* file) const
  47. {
  48. unsigned int size;
  49. char* pointer;
  50. file->read (&size, 4);
  51. // the string doesnt include the null terminator
  52. size ++;
  53. pointer = new char [size];
  54. memset (pointer, 0, size);
  55. file->read (pointer, size - 1);
  56. if (strcmp (pointer, "PKGV0002") != 0 && strcmp (pointer, "PKGV0001") != 0)
  57. {
  58. delete [] pointer;
  59. return false;
  60. }
  61. delete [] pointer;
  62. return true;
  63. }
  64. //! Check to see if the loader can create archives of this type.
  65. bool CArchiveLoaderPkg::isALoadableFileFormat(irr::io::E_FILE_ARCHIVE_TYPE fileType) const
  66. {
  67. return false;
  68. }
  69. CPkgReader::CPkgReader (irr::io::IReadFile* file, bool ignoreCase, bool ignorePaths)
  70. : CFileList((file ? file->getFileName() : irr::io::path("")), ignoreCase, ignorePaths), mFile(file)
  71. {
  72. if (this->mFile)
  73. {
  74. this->mFile->grab ();
  75. this->scanPkgHeader ();
  76. }
  77. }
  78. CPkgReader::~CPkgReader()
  79. {
  80. if (this->mFile)
  81. this->mFile->drop();
  82. }
  83. //! get the archive type
  84. irr::io::E_FILE_ARCHIVE_TYPE CPkgReader::getType() const
  85. {
  86. return irr::io::E_FILE_ARCHIVE_TYPE::EFAT_ZIP;
  87. }
  88. const irr::io::IFileList* CPkgReader::getFileList() const
  89. {
  90. return this;
  91. }
  92. void CPkgReader::scanPkgHeader ()
  93. {
  94. char* headerVersion = this->readSizedString ();
  95. if (strcmp ("PKGV0002", headerVersion) != 0 && strcmp ("PKGV0001", headerVersion) != 0)
  96. {
  97. WallpaperEngine::Irrlicht::device->getLogger ()->log ("Unexpected package header... Aborting load", this->mFile->getFileName ().c_str (), irr::ELL_ERROR);
  98. delete [] headerVersion;
  99. return;
  100. }
  101. delete [] headerVersion;
  102. unsigned int entriesCount;
  103. this->mFile->read (&entriesCount, 4);
  104. for (int i = 0; i < entriesCount; i ++)
  105. {
  106. char* filename = this->readSizedString ();
  107. unsigned int offset, length;
  108. this->mFile->read (&offset, 4);
  109. this->mFile->read (&length, 4);
  110. this->addItem (filename, offset, length, false);
  111. delete [] filename;
  112. }
  113. // after the header is read we have to update the actual offsets
  114. for (int i = 0; i < this->Files.size (); i ++)
  115. {
  116. this->Files [i].Offset += this->mFile->getPos ();
  117. }
  118. }
  119. char* CPkgReader::readSizedString ()
  120. {
  121. unsigned int size;
  122. char* pointer;
  123. this->mFile->read (&size, 4);
  124. // the string doesnt include the null terminator
  125. size ++;
  126. pointer = new char [size];
  127. memset (pointer, 0, size);
  128. this->mFile->read (pointer, size - 1);
  129. return pointer;
  130. }
  131. irr::io::IReadFile* CPkgReader::createAndOpenFile (const irr::io::path& filename)
  132. {
  133. irr::s32 index = this->findFile (filename, false);
  134. if (index != -1)
  135. return createAndOpenFile (index);
  136. return nullptr;
  137. }
  138. irr::io::IReadFile* CPkgReader::createAndOpenFile (irr::u32 index)
  139. {
  140. if (index > this->Files.size ())
  141. return nullptr;
  142. const SFileListEntry entry = Files [index];
  143. return irr::io::createLimitReadFile (entry.FullName, mFile, entry.Offset, entry.Size);
  144. }