/*=========================================================================== * * File: DFBSA.H * Author: Dave Humphrey (uesp@m0use.net) * Created On: Wednesday, June 20, 2001 * * Defines the base class CDFBsaFile for handling Daggerfall's BSA type * data files. * *=========================================================================*/ #ifndef __DFBSA_H #define __DFBSA_H /*=========================================================================== * * Begin Required Include Files * *=========================================================================*/ #include "common/file/genfile.h" #include "uesp/dagger/common/dfcommon.h" /*=========================================================================== * End of Required Include Files *=========================================================================*/ /*=========================================================================== * * Begin Definitions * *=========================================================================*/ /* Types of BSA directories */ #define DFBSA_DIR_NAME (0x0100) #define DFBSA_DIR_VALUE (0x0200) /* Size of buffer used to extract records */ #define DFBSA_EXTRACT_BUFFERSIZE 32000 /*=========================================================================== * End of Definitions *=========================================================================*/ /*=========================================================================== * * Begin Type Definitions * *=========================================================================*/ /* Save and turn-off structure alignment */ #pragma pack(push, 1) /* BSA filename directory type record structure */ typedef struct { char Name[14]; long Size; } dfbsa_namedir_t; /* BSA value directory type record structure */ typedef struct { long Value; long Size; } dfbsa_valuedir_t; /* Restore structure alignment */ #pragma pack(pop) /*=========================================================================== * End of Type Definitions *=========================================================================*/ /*=========================================================================== * * Begin Class CDFBsaFile Definition * * Base class for handling a Daggerfall BSA type file. Derived from the * basic CGenFile class. * *=========================================================================*/ class CDFBsaFile : public CGenFile { /*---------- Begin Private Class Members ----------------------*/ private: short m_NumRecords; /* Number of directory entries */ short m_DirType; /* Type of BSA directory */ boolean m_ReadHeader; /* Flags to indicate whether basic BSA */ boolean m_ReadDir; /* sections have been input */ char* m_pFilename; /* The current BSA filename */ dfbsa_namedir_t* m_pNameDir; /* Pointers to an array of directory records */ dfbsa_valuedir_t* m_pValueDir; long* m_pRecordOffsets; /* Pointer to array of file offsets */ /*---------- Begin Protected Class Methods --------------------*/ protected: /* Create the directory arrays */ void AllocateDirectory (void); void ComputeRecordOffsets (void); /* Helper function to dump a directory entry */ void DumpDirEntry (FILE* pFileHandle, const int Index); /* Get a valid pointer to the directory array */ void* GetDirectory (void); /* Input basic BSA sections */ boolean ReadHeader (void); boolean ReadDirectory (void); /*---------- Begin Public Class Methods -----------------------*/ public: /* Class Constructors/Destructors */ CDFBsaFile(); virtual void Destroy (void); /* Ensures the object contains valid data */ boolean AssertValid (void); /* Close an opened BSA file */ virtual void Close (void); /* Dump object information to a file stream */ void Dump (FILE* pFileHandle); /* Extract a binary record to the given filename */ boolean Extract (const char* pFilename, const size_t Index); /* Search for a directory based on a name/value */ int FindRecord (const long Value); int FindRecord (const char* pName); /* Get class members */ short GetNumRecords (void) const; short GetDirType (void) const; long GetRecordOffset (const size_t Index) const; long GetRecordSize (const size_t Index) const; char* GetRecordName (const size_t Index) const; long GetRecordValue (const size_t Index) const; /* Compute the size, in bytes, of the directory */ long GetDirSize (void) const; long GetDirRecordSize (void) const; /* Check a directory file index */ boolean IsValidIndex (const size_t Index) const; /* Check object state */ boolean HaveReadDirectory (void) const; boolean HaveReadHeader (void) const; /* Open a BSA file for input/output */ virtual boolean Open (const char* pFilename, const char* pMode); /* Set class members */ void SetFilename (const char* pString); }; /*=========================================================================== * End of Class CDFBsaFile Definition *=========================================================================*/ /*=========================================================================== * * Begin CDFBsaFile Inline Methods * *=========================================================================*/ /* Get class members */ inline short CDFBsaFile::GetNumRecords (void) const { return (m_NumRecords); } inline short CDFBsaFile::GetDirType (void) const { return (m_DirType); } /* Get the size of a BSA file record */ inline long CDFBsaFile::GetRecordSize (const size_t Index) const { IASSERT((short)Index < m_NumRecords && m_ReadDir); return ((m_DirType == DFBSA_DIR_VALUE) ? m_pValueDir[Index].Size : m_pNameDir[Index].Size); } /* Get the offset to a BSA file record */ inline long CDFBsaFile::GetRecordOffset (const size_t Index) const { IASSERT((short)Index < m_NumRecords && m_ReadDir && m_pRecordOffsets != NULL); return m_pRecordOffsets[Index]; } /* Get the name of a BSA file record */ inline char* CDFBsaFile::GetRecordName (const size_t Index) const { IASSERT((short)Index < m_NumRecords && m_ReadDir && m_DirType == DFBSA_DIR_NAME); return ((m_DirType == DFBSA_DIR_VALUE) ? NULL : m_pNameDir[Index].Name); } /* Get the value of a BSA file record */ inline long CDFBsaFile::GetRecordValue (const size_t Index) const { IASSERT((short)Index < m_NumRecords && m_ReadDir && m_DirType == DFBSA_DIR_VALUE); return ((m_DirType == DFBSA_DIR_VALUE) ? m_pValueDir[Index].Value : 0); } /* Compute the size, in bytes, of the directory */ inline long CDFBsaFile::GetDirSize (void) const { return (GetDirRecordSize() * (long)m_NumRecords); } inline long CDFBsaFile::GetDirRecordSize (void) const { return ((m_DirType == DFBSA_DIR_NAME) ? sizeof(dfbsa_namedir_t) : sizeof(dfbsa_valuedir_t)); } /* Check a directory file index */ inline boolean CDFBsaFile::IsValidIndex (const size_t Index) const { return ( ((short)Index < m_NumRecords) ? TRUE : FALSE); } /* Check object state */ inline boolean CDFBsaFile::HaveReadDirectory (void) const { return (m_ReadDir); } inline boolean CDFBsaFile::HaveReadHeader (void) const { return (m_ReadHeader); } /* Set class members */ inline void CDFBsaFile::SetFilename (const char* pString) { ReplaceString(&m_pFilename, pString); } /*=========================================================================== * End of CDFBsaFile Inline Methods *=========================================================================*/ #endif /*=========================================================================== * End of File Dfbsa.H *=========================================================================*/