From 7028cbe09c688437910a25623098762bf0fa592d Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Mon, 28 Mar 2016 22:28:34 +1000 Subject: Move Irrlicht to src/others. --- .../irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp | 277 +++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp') diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp new file mode 100644 index 0000000..fc02786 --- /dev/null +++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CNPKReader.cpp @@ -0,0 +1,277 @@ +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// Copyright (C) 2009-2012 Christian Stehno +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h +// Based on the NPK reader from Irrlicht + +#include "CNPKReader.h" + +#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + +#include "os.h" +#include "coreutil.h" + +#ifdef _DEBUG +#define IRR_DEBUG_NPK_READER +#endif + +namespace irr +{ +namespace io +{ + +namespace +{ + bool isHeaderValid(const SNPKHeader& header) + { + const c8* const tag = header.Tag; + return tag[0] == '0' && + tag[1] == 'K' && + tag[2] == 'P' && + tag[3] == 'N'; + } +} // end namespace + + +//! Constructor +CArchiveLoaderNPK::CArchiveLoaderNPK( io::IFileSystem* fs) +: FileSystem(fs) +{ +#ifdef _DEBUG + setDebugName("CArchiveLoaderNPK"); +#endif +} + + +//! returns true if the file maybe is able to be loaded by this class +bool CArchiveLoaderNPK::isALoadableFileFormat(const io::path& filename) const +{ + return core::hasFileExtension(filename, "npk"); +} + +//! Check to see if the loader can create archives of this type. +bool CArchiveLoaderNPK::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const +{ + return fileType == EFAT_NPK; +} + +//! Creates an archive from the filename +/** \param file File handle to check. +\return Pointer to newly created archive, or 0 upon error. */ +IFileArchive* CArchiveLoaderNPK::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + io::IReadFile* file = FileSystem->createAndOpenFile(filename); + + if (file) + { + archive = createArchive(file, ignoreCase, ignorePaths); + file->drop (); + } + + return archive; +} + +//! creates/loads an archive from the file. +//! \return Pointer to the created archive. Returns 0 if loading failed. +IFileArchive* CArchiveLoaderNPK::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const +{ + IFileArchive *archive = 0; + if ( file ) + { + file->seek ( 0 ); + archive = new CNPKReader(file, ignoreCase, ignorePaths); + } + return archive; +} + + +//! Check if the file might be loaded by this class +/** Check might look into the file. +\param file File handle to check. +\return True if file seems to be loadable. */ +bool CArchiveLoaderNPK::isALoadableFileFormat(io::IReadFile* file) const +{ + SNPKHeader header; + + file->read(&header, sizeof(header)); + + return isHeaderValid(header); +} + + +/*! + NPK Reader +*/ +CNPKReader::CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths) +: CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file) +{ +#ifdef _DEBUG + setDebugName("CNPKReader"); +#endif + + if (File) + { + File->grab(); + if (scanLocalHeader()) + sort(); + else + os::Printer::log("Failed to load NPK archive."); + } +} + + +CNPKReader::~CNPKReader() +{ + if (File) + File->drop(); +} + + +const IFileList* CNPKReader::getFileList() const +{ + return this; +} + + +bool CNPKReader::scanLocalHeader() +{ + SNPKHeader header; + + // Read and validate the header + File->read(&header, sizeof(header)); + if (!isHeaderValid(header)) + return false; + + // Seek to the table of contents +#ifdef __BIG_ENDIAN__ + header.Offset = os::Byteswap::byteswap(header.Offset); + header.Length = os::Byteswap::byteswap(header.Length); +#endif + header.Offset += 8; + core::stringc dirName; + bool inTOC=true; + // Loop through each entry in the table of contents + while (inTOC && (File->getPos() < File->getSize())) + { + // read an entry + char tag[4]={0}; + SNPKFileEntry entry; + File->read(tag, 4); + const int numTag = MAKE_IRR_ID(tag[3],tag[2],tag[1],tag[0]); + int size; + + bool isDir=true; + + switch (numTag) + { + case MAKE_IRR_ID('D','I','R','_'): + { + File->read(&size, 4); + readString(entry.Name); + entry.Length=0; + entry.Offset=0; +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("Dir", entry.Name); +#endif + } + break; + case MAKE_IRR_ID('F','I','L','E'): + { + File->read(&size, 4); + File->read(&entry.Offset, 4); + File->read(&entry.Length, 4); + readString(entry.Name); + isDir=false; +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("File", entry.Name); +#endif +#ifdef __BIG_ENDIAN__ + entry.Offset = os::Byteswap::byteswap(entry.Offset); + entry.Length = os::Byteswap::byteswap(entry.Length); +#endif + } + break; + case MAKE_IRR_ID('D','E','N','D'): + { + File->read(&size, 4); + entry.Name=""; + entry.Length=0; + entry.Offset=0; + const s32 pos = dirName.findLast('/', dirName.size()-2); + if (pos==-1) + dirName=""; + else + dirName=dirName.subString(0, pos); +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("Dirend", dirName); +#endif + } + break; + default: + inTOC=false; + } + // skip root dir + if (isDir) + { + if (!entry.Name.size() || (entry.Name==".") || (entry.Name=="")) + continue; + dirName += entry.Name; + dirName += "/"; + } +#ifdef IRR_DEBUG_NPK_READER + os::Printer::log("Name", entry.Name); +#endif + addItem((isDir?dirName:dirName+entry.Name), entry.Offset+header.Offset, entry.Length, isDir); + } + return true; +} + + +//! opens a file by file name +IReadFile* CNPKReader::createAndOpenFile(const io::path& filename) +{ + s32 index = findFile(filename, false); + + if (index != -1) + return createAndOpenFile(index); + + return 0; +} + + +//! opens a file by index +IReadFile* CNPKReader::createAndOpenFile(u32 index) +{ + if (index >= Files.size() ) + return 0; + + const SFileListEntry &entry = Files[index]; + return createLimitReadFile( entry.FullName, File, entry.Offset, entry.Size ); +} + +void CNPKReader::readString(core::stringc& name) +{ + short stringSize; + char buf[256]; + File->read(&stringSize, 2); +#ifdef __BIG_ENDIAN__ + stringSize = os::Byteswap::byteswap(stringSize); +#endif + name.reserve(stringSize); + while(stringSize) + { + const short next = core::min_(stringSize, (short)255); + File->read(buf,next); + buf[next]=0; + name.append(buf); + stringSize -= next; + } +} + + +} // end namespace io +} // end namespace irr + +#endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ + -- cgit v1.1