// Copyright (C) 2009 Gaz Davidson // for copying permissions see readme.txt #ifndef __C_RES_LOADER_H_INCLUDED__ #define __C_RES_LOADER_H_INCLUDED__ #include "IFileArchive.h" #include "irrArray.h" #include "IWriteFile.h" #include "IReadFile.h" namespace irr { namespace io { class IFileSystem; #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT #elif defined( __GNUC__ ) # define PACK_STRUCT __attribute__((packed)) #else # error compiler not supported #endif enum E_RESOURCE_TYPE { //! A single cursor ERSRCT_CURSOR = 1, //! A bitmap image ERSRCT_BITMAP = 2, //! A single icon ERSRCT_ICON = 3, //! A menu ERSRCT_MENU = 4, //! A dialog ERSRCT_DIALOG = 5, //! a string table ERSRCT_STRING = 6, //! a collection of fonts ERSRCT_FONT_DIR = 7, //! a single font ERSRCT_FONT = 8, //! keyboard shortcut table ERSRCT_ACCELERATORS = 9, //! user data ERSRCT_USER = 10, //! list of messages ERSRCT_MESSAGE_TABLE = 11, //! a collection of cursors ERSRCT_CURSOR_GROUP = 12, //! a group of icons ERSRCT_ICON_GROUP = 14, //! Version string ERSRCT_VERSION = 16, //! a theme manifest ERSRCT_MANIFEST = 24, //! This resource type is a name //! Also causes this enum to compile as u32 ERSRCT_NAMED_RESOURCE_TYPE = 0x7FFFFFFF }; // offset to this signature is given at offset 60 const u32 PEBinarySignature = MAKE_IRR_ID('P', 'E', 0, 0); // this immediately follows the signature struct SCOFFFileHeader { u16 MachineType; u16 NumberOfSections; // we find the resource section in here u32 TimeStamp; u32 PointerToSymbolTable; u32 NumberOfSymbols; u16 SizeOfOptionalHeader; // we skip the optional header u16 Characteristics; } PACK_STRUCT; // the optional header follows next, we skip it and get on to the // section headers, which come next. // usually the resource section will be the third one, but we need to // check the name... struct SSectionHeader { c8 Name[8]; // name of the section u32 VirtualSize; u32 VirtualAddress; u32 SizeOfRawData; u32 PointerToRawData; // file pointer to the data section! u32 PointerToRelocations; u32 PointerToLinenumbers; u16 NumberOfRelocations; u16 NumberOfLinenumbers; u32 Characteristics; } PACK_STRUCT; // once we've spun on to the resource directory, we can start extracting // the headers inside it. This is the head of a directory- struct SResourceDirectoryTable { u32 Characteristics; u32 TimeStamp; u16 MajorVersion; u16 MinorVersion; u16 NameEntryCount; u16 IDEntryCount; } PACK_STRUCT; // then we get a list of directory entries, the first batch are name entries // and the second batch are ID entries. struct SResourceDirectoryEntry { u32 NameRVAorIntegerID; // offset to the name, or the integer ID of this dir entry u32 DataEntryRVAorSubdirectoryRVA; // if high bit = 0 resource data address, // if high bit = 1 address of next dir table } PACK_STRUCT; // names are strings with u16 length, followed by a bunch of unicode characters. // screw decoding unicode, we'll just use wchar_t. // It's not like anything in here even has a name, data is usually an ID number and dirs have set names. // Finally! we reach the meat :) // using this bad boy we can extract the icon or other resource data. struct SResourceData { u32 DataRVA; // relative address to data u32 Size; // size in bytes u32 Codepage; // usually unicode u32 Reserved; // must be 0 } PACK_STRUCT; // Default alignment #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT class CArchiveLoaderRes : public IArchiveLoader { public: //! Constructor CArchiveLoaderRes(io::IFileSystem* fs); //! returns true if the file maybe is able to be loaded by this class //! based on the file extension (e.g. ".exe") virtual bool isALoadableFileFormat(const core::string& filename) const; //! Creates an archive from the filename virtual IFileArchive* createArchive(const core::string& filename, bool ignoreCase, bool ignorePaths) const; //! Check if the file might be loaded by this class virtual bool isALoadableFileFormat(io::IReadFile* file) const; //! creates/loads an archive from the file. 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 E_FILE_ARCHIVE_TYPE(MAKE_IRR_ID('r', 's', 'r', 'c')); } private: io::IFileSystem* FileSystem; }; class CResReader : public IFileArchive { public: //! constructor CResReader(IFileSystem *fs, IReadFile* file, bool ignoreCase, bool ignorePaths); //! destructor virtual ~CResReader(); //! opens a file by file name virtual IReadFile* createAndOpenFile(const core::string& filename); //! opens a file by index virtual IReadFile* createAndOpenFile(u32 index); //! returns count of files in archive virtual u32 getFileCount() const; //! returns data of file virtual const IFileArchiveEntry* getFileInfo(u32 index); //! returns fileindex virtual s32 findFile(const core::string& filename); //! return the id of the file Archive virtual const core::string& getArchiveName(); //! get the class Type virtual E_FILE_ARCHIVE_TYPE getType() const { return E_FILE_ARCHIVE_TYPE(MAKE_IRR_ID('r', 's', 'r', 'c')); } private: #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( push, packing ) # pragma pack( 1 ) # define PACK_STRUCT #elif defined( __GNUC__ ) # define PACK_STRUCT __attribute__((packed)) #else # error compiler not supported #endif //! Header to fix BMP files for loading struct SBMPHeader { struct SBMPFileHeader { u16 Id; u32 FileSize; u32 Reserved; u32 BitmapDataOffset; } FileHeader; u32 BitmapHeaderSize; u32 Width; u32 Height; u16 Planes; u16 BPP; u32 Compression; u32 BitmapDataSize; u32 PixelPerMeterX; u32 PixelPerMeterY; u32 Colors; u32 ImportantColors; } PACK_STRUCT; struct SIcoFileHeader { u16 reserved; // 0 u16 resourceType; // 1 for icon, 2 for cursor u16 itemCount; } PACK_STRUCT; struct SIconDetails { u8 width; // width in pixels u8 height; // height in pixels u8 colourCount; // only in paletted image, 0 for 24/32 bit u8 reserved; // 0 u16 planes; // 1 u16 bpp; // 1, 4, 8, 24 or 32 bit u32 size; // size of icon data including header union { u32 offset; // position in the file (absolute) u16 resourceID; // ID of the resource }; } PACK_STRUCT; // Default alignment #if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) # pragma pack( pop, packing ) #endif #undef PACK_STRUCT //! entry which describes resource entries in the executable struct SResArchiveEntry : public IFileArchiveEntry { // the data type, decides extension E_RESOURCE_TYPE ResourceType; // if the resource type is a name then it goes here core::string ResourceTypeName; // from start of file u32 Offset; // length in bytes u32 Length; }; u32 populateFileList(); bool addFolder(c8 level, SResArchiveEntry entry, u32 offset); bool getName(core::string& name, u32 offset); void addFileExtension(SResArchiveEntry &entry); IFileSystem* FileSystem; IReadFile* File; // offset of the descriptions of resources u32 ResourceTreeAddress; // offset of the raw data u32 ResourceDataAddress; bool IgnoreCase; bool IgnorePaths; core::array FileList; core::string Base; }; // todo: remove this once it is implemented in Irrlicht //! Provides write acess to an array as if it is a file. class CResMemoryReadWriteFile : public virtual IWriteFile, public virtual IReadFile { public: CResMemoryReadWriteFile(const c16* filename=0); //! Reads an amount of bytes from the file. //! \param buffer: Pointer to buffer of bytes to write. //! \param sizeToWrite: Amount of bytes to wrtie to the file. //! \return Returns how much bytes were written. virtual s32 write(const void* buffer, u32 sizeToWrite); //! Changes position in file, returns true if successful. //! \param finalPos: Destination position in the file. //! \param relativeMovement: If set to true, the position in the file is //! changed relative to current position. Otherwise the position is changed //! from begin of file. //! \return Returns true if successful, otherwise false. virtual bool seek(long finalPos, bool relativeMovement = false); //! Returns size of file. //! \return Returns the size of the file in bytes. virtual long getSize() const; //! Reads an amount of bytes from the file. //! \param buffer: Pointer to buffer where to read bytes will be written to. //! \param sizeToRead: Amount of bytes to read from the file. //! \return Returns how much bytes were read. virtual s32 read(void* buffer, u32 sizeToRead); //! Returns the current position in the file. //! \return Returns the current position in the file in bytes. virtual long getPos() const; //! Returns name of file. //! \return Returns the file name as zero terminated character string. virtual const core::string& getFileName() const; //! Returns file data as an array core::array& getData(); private: core::array Data; core::string FileName; long Pos; }; } // namespace io } // namespace irr #endif // __C_RES_LOADER_H_INCLUDED__