CPkgReader.cpp 4.6 KB

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