Commit c35ca282 authored by hybrid's avatar hybrid

Add Nebula device archive reader.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@2820 dfc29bdd-3216-0410-991c-e03cc46cb475
parent fcf0229a
......@@ -36,6 +36,9 @@ enum E_FILE_ARCHIVE_TYPE
//! An ID Software PAK archive
EFAT_PAK = MAKE_IRR_ID('P','A','K', 0),
//! A Nebula Device archive
EFAT_NPK = MAKE_IRR_ID('N','P','K', 0),
//! A Tape ARchive
EFAT_TAR = MAKE_IRR_ID('T','A','R', 0),
......
......@@ -352,6 +352,8 @@ B3D, MS3D or X meshes */
#define __IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_
//! Define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_ if you want to open ID software PAK archives
#define __IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_
//! Define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_ if you want to open Nebula Device NPK archives
#define __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
//! Define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_ if you want to open TAR archives
#define __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_
......
......@@ -10,6 +10,7 @@
#include "CZipReader.h"
#include "CMountPointReader.h"
#include "CPakReader.h"
#include "CNPKReader.h"
#include "CTarReader.h"
#include "CFileList.h"
#include "CXMLReader.h"
......@@ -67,6 +68,10 @@ CFileSystem::CFileSystem()
ArchiveLoader.push_back(new CArchiveLoaderPAK(this));
#endif
#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
ArchiveLoader.push_back(new CArchiveLoaderNPK(this));
#endif
#ifdef __IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_
ArchiveLoader.push_back(new CArchiveLoaderTAR(this));
#endif
......
// Copyright (C) 2002-2009 Nikolaus Gebhardt
// Copyright (C) 2009 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() : "", 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=="<noname>"))
continue;
dirName += entry.Name;
dirName += "/";
}
#ifdef IRR_DEBUG_NPK_READER
os::Printer::log("Name", entry.Name);
#endif
addItem(isDir?dirName:dirName+entry.Name, entry.Length, isDir, Offsets.size());
Offsets.push_back(entry.Offset+header.Offset);
}
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 createLimitReadFile(Files[index].FullName, File, Offsets[Files[index].ID], Files[index].Size);
}
else
return 0;
}
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_
// Copyright (C) 2002-2009 Nikolaus Gebhardt
// Copyright (C) 2009 Christian Stehno
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef __C_NPK_READER_H_INCLUDED__
#define __C_NPK_READER_H_INCLUDED__
#include "IrrCompileConfig.h"
#ifdef __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
#include "IReferenceCounted.h"
#include "IReadFile.h"
#include "irrArray.h"
#include "irrString.h"
#include "IFileSystem.h"
#include "CFileList.h"
namespace irr
{
namespace io
{
namespace
{
//! File header containing location and size of the table of contents
struct SNPKHeader
{
// Don't change the order of these fields! They must match the order stored on disk.
c8 Tag[4];
u32 Length;
u32 Offset;
};
//! An entry in the NPK file's table of contents.
struct SNPKFileEntry
{
core::stringc Name;
u32 Offset;
u32 Length;
};
} // end namespace
//! Archiveloader capable of loading Nebula Device 2 NPK Archives
class CArchiveLoaderNPK : public IArchiveLoader
{
public:
//! Constructor
CArchiveLoaderNPK(io::IFileSystem* fs);
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".zip")
virtual bool isALoadableFileFormat(const io::path& filename) const;
//! 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. */
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! Check to see if the loader can create archives of this type.
/** Check based on the archive type.
\param fileType The archive type to check.
\return True if the archile loader supports this type, false if not */
virtual bool isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const;
//! Creates an archive from the filename
/** \param file File handle to check.
\return Pointer to newly created archive, or 0 upon error. */
virtual IFileArchive* createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const;
//! creates/loads an archive from the file.
//! \return Pointer to the created archive. Returns 0 if loading failed.
virtual io::IFileArchive* createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const;
//! Returns the type of archive created by this loader
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_NPK; }
private:
io::IFileSystem* FileSystem;
};
//! reads from NPK
class CNPKReader : public virtual IFileArchive, virtual CFileList
{
public:
CNPKReader(IReadFile* file, bool ignoreCase, bool ignorePaths);
virtual ~CNPKReader();
// file archive methods
//! return the id of the file Archive
virtual const io::path& getArchiveName() const
{
return File->getFileName();
}
//! opens a file by file name
virtual IReadFile* createAndOpenFile(const io::path& filename);
//! opens a file by index
virtual IReadFile* createAndOpenFile(u32 index);
//! returns the list of files
virtual const IFileList* getFileList() const;
//! get the class Type
virtual E_FILE_ARCHIVE_TYPE getType() const { return EFAT_NPK; }
private:
//! scans for a local header, returns false if the header is invalid
bool scanLocalHeader();
void readString(core::stringc& name);
IReadFile* File;
//! Contains offsets of the files from the start of the archive file
core::array<u32> Offsets;
};
} // end namespace io
} // end namespace irr
#endif // __IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_
#endif // __C_NPK_READER_H_INCLUDED__
......@@ -808,6 +808,8 @@
<Unit filename="CPLYMeshWriter.h" />
<Unit filename="CPakReader.cpp" />
<Unit filename="CPakReader.h" />
<Unit filename="CNPKReader.cpp" />
<Unit filename="CNPKReader.h" />
<Unit filename="CParticleAnimatedMeshSceneNodeEmitter.cpp" />
<Unit filename="CParticleAttractionAffector.cpp" />
<Unit filename="CParticleBoxEmitter.cpp" />
......
......@@ -9,7 +9,7 @@ CppCompiler=-D__GNUWIN32__ -W -DWIN32 -DNDEBUG -D_WINDOWS -D_MBCS -D_USRDLL -DIR
Includes=..\..\include;zlib
Linker=-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lwinmm -lopengl32_@@_
Libs=
UnitCount=625
UnitCount=627
Folders=doc,include,include/core,include/gui,include/io,include/scene,include/video,Irrlicht,Irrlicht/extern,Irrlicht/extern/jpeglib,Irrlicht/extern/libpng,Irrlicht/extern/zlib,Irrlicht/gui,Irrlicht/io,Irrlicht/io/archive,Irrlicht/io/attributes,Irrlicht/io/file,Irrlicht/io/xml,Irrlicht/irr,Irrlicht/irr/IrrlichtDevice,Irrlicht/scene,Irrlicht/scene/animators,Irrlicht/scene/collision,Irrlicht/scene/mesh,Irrlicht/scene/mesh/loaders,Irrlicht/scene/mesh/writers,Irrlicht/scene/nodes,Irrlicht/scene/nodes/particles,Irrlicht/video,"Irrlicht/video/Burning Video",Irrlicht/video/DirectX8,Irrlicht/video/DirectX9,Irrlicht/video/Null,Irrlicht/video/Null/Loader,Irrlicht/video/Null/Writer,Irrlicht/video/OpenGL,Irrlicht/video/Software
ObjFiles=
PrivateResource=
......@@ -6298,3 +6298,23 @@ Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit626]
FileName=CNPKReader.h
CompileCpp=1
Folder=Irrlicht/io/archive
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
[Unit627]
FileName=CNPKReader.cpp
CompileCpp=1
Folder=Irrlicht/io/archive
Compile=1
Link=1
Priority=1000
OverrideBuildCmd=0
BuildCmd=
......@@ -1978,6 +1978,12 @@
<File
RelativePath=".\CPakReader.h">
</File>
<File
RelativePath=".\CNPKReader.cpp">
</File>
<File
RelativePath=".\CNPKReader.h">
</File>
<File
RelativePath=".\CReadFile.cpp">
</File>
......
......@@ -2758,6 +2758,14 @@
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CNPKReader.cpp"
>
</File>
<File
RelativePath="CNPKReader.h"
>
</File>
<File
RelativePath="CReadFile.cpp"
>
......
......@@ -3115,6 +3115,14 @@
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CNPKReader.cpp"
>
</File>
<File
RelativePath="CNPKReader.h"
>
</File>
<File
RelativePath="CReadFile.cpp"
>
......
......@@ -2385,6 +2385,14 @@
RelativePath="CPakReader.h"
>
</File>
<File
RelativePath="CNPKReader.cpp"
>
</File>
<File
RelativePath="CNPKReader.h"
>
</File>
<File
RelativePath="CTarReader.cpp"
>
......
......@@ -1131,6 +1131,12 @@
<File
RelativePath=".\CPakReader.h">
</File>
<File
RelativePath=".\CNPKReader.cpp">
</File>
<File
RelativePath=".\CNPKReader.h">
</File>
<File
RelativePath=".\CTarReader.cpp">
</File>
......
......@@ -41,7 +41,7 @@ IRRVIDEOOBJ = ['CVideoModeList.cpp', 'CFPSCounter.cpp'] + IRRDRVROBJ + IRRIMAGEO
IRRSWRENDEROBJ = ['CSoftwareDriver.cpp', 'CSoftwareTexture.cpp', 'CTRFlat.cpp', 'CTRFlatWire.cpp', 'CTRGouraud.cpp', 'CTRGouraudWire.cpp', 'CTRTextureFlat.cpp', 'CTRTextureFlatWire.cpp', 'CTRTextureGouraud.cpp', 'CTRTextureGouraudAdd.cpp', 'CTRTextureGouraudNoZ.cpp', 'CTRTextureGouraudWire.cpp', 'CZBuffer.cpp', 'CTRTextureGouraudVertexAlpha2.cpp', 'CTRTextureGouraudNoZ2.cpp', 'CTRTextureLightMap2_M2.cpp', 'CTRTextureLightMap2_M4.cpp', 'CTRTextureLightMap2_M1.cpp', 'CSoftwareDriver2.cpp', 'CSoftwareTexture2.cpp', 'CTRTextureGouraud2.cpp', 'CTRGouraud2.cpp', 'CTRGouraudAlpha2.cpp', 'CTRGouraudAlphaNoZ2.cpp', 'CTRTextureDetailMap2.cpp', 'CTRTextureGouraudAdd2.cpp', 'CTRTextureGouraudAddNoZ2.cpp', 'CTRTextureWire2.cpp', 'CTRTextureLightMap2_Add.cpp', 'CTRTextureLightMapGouraud2_M4.cpp', 'IBurningShader.cpp', 'CTRTextureBlend.cpp', 'CTRTextureGouraudAlpha.cpp', 'CTRTextureGouraudAlphaNoZ.cpp', 'CDepthBuffer.cpp', 'CBurningShader_Raster_Reference.cpp'];
IRRIOOBJ = ['CFileList.cpp', 'CFileSystem.cpp', 'CLimitReadFile.cpp', 'CMemoryReadFile.cpp', 'CReadFile.cpp', 'CWriteFile.cpp', 'CXMLReader.cpp', 'CXMLWriter.cpp', 'CZipReader.cpp', 'CPakReader.cpp', 'irrXML.cpp', 'CAttributes.cpp'];
IRRIOOBJ = ['CFileList.cpp', 'CFileSystem.cpp', 'CLimitReadFile.cpp', 'CMemoryReadFile.cpp', 'CReadFile.cpp', 'CWriteFile.cpp', 'CXMLReader.cpp', 'CXMLWriter.cpp', 'CZipReader.cpp', 'CPakReader.cpp', 'CNPKReader.cpp', 'irrXML.cpp', 'CAttributes.cpp'];
IRROTHEROBJ = ['CIrrDeviceSDL.cpp', 'CIrrDeviceLinux.cpp', 'CIrrDeviceStub.cpp', 'CIrrDeviceWin32.cpp', 'CLogger.cpp', 'COSOperator.cpp', 'Irrlicht.cpp', 'os.cpp'];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment