mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 20:12:21 +02:00
208 lines
6.5 KiB
C
208 lines
6.5 KiB
C
![]() |
//////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// AkFilePackageLUT.h
|
||
|
//
|
||
|
// This class parses the header of file packages that were created with the
|
||
|
// AkFilePackager utility app (located in ($WWISESDK)/samples/FilePackager/),
|
||
|
// and looks-up files at run-time.
|
||
|
//
|
||
|
// The header of these file packages contains look-up tables that describe the
|
||
|
// internal offset of each file it references, their block size (required alignment),
|
||
|
// and their language. Each combination of AkFileID and Language ID is unique.
|
||
|
//
|
||
|
// The language was created dynamically when the package was created. The header
|
||
|
// also contains a map of language names (strings) to their ID, so that the proper
|
||
|
// language-specific version of files can be resolved. The language name that is stored
|
||
|
// matches the name of the directory that is created by the Wwise Bank Manager,
|
||
|
// except for the trailing slash.
|
||
|
//
|
||
|
// Copyright (c) 2007-2009 Audiokinetic Inc. / All Rights Reserved
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#ifndef _AK_FILE_PACKAGE_LUT_H_
|
||
|
#define _AK_FILE_PACKAGE_LUT_H_
|
||
|
|
||
|
#include <AK/SoundEngine/Common/IAkStreamMgr.h>
|
||
|
#include <AK/Tools/Common/AkAssert.h>
|
||
|
|
||
|
// AK file packager definitions.
|
||
|
#define AKPK_CURRENT_VERSION (1)
|
||
|
|
||
|
#define AKPK_HEADER_CHUNK_DEF_SIZE (8) // The header chunk definition is 8 bytes wide.
|
||
|
|
||
|
#define AKPK_FILE_FORMAT_TAG \
|
||
|
AkmmioFOURCC('A','K','P','K')
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Name: class CAkFilePackageLUT.
|
||
|
// Desc: Keeps pointers to various parts of the header. Offers look-up services
|
||
|
// for file look-up and soundbank ID retrieval.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CAkFilePackageLUT
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
static const AkUInt16 AK_INVALID_LANGUAGE_ID = 0;
|
||
|
|
||
|
// Ensure no padding is done because this structure is mapped to file content
|
||
|
#pragma pack(push, 4)
|
||
|
template <class T_FILEID>
|
||
|
struct AkFileEntry
|
||
|
{
|
||
|
T_FILEID fileID; // File identifier.
|
||
|
AkUInt32 uBlockSize; // Size of one block, required alignment (in bytes).
|
||
|
AkUInt32 uFileSize; // File size in bytes.
|
||
|
AkUInt32 uStartBlock;// Start block, expressed in terms of uBlockSize.
|
||
|
AkUInt32 uLanguageID;// Language ID. AK_INVALID_LANGUAGE_ID if not language-specific.
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
CAkFilePackageLUT();
|
||
|
virtual ~CAkFilePackageLUT();
|
||
|
|
||
|
// Create a new LUT from a packaged file header.
|
||
|
// The LUT sets pointers to appropriate location inside header data (in_pData).
|
||
|
AKRESULT Setup(
|
||
|
AkUInt8 * in_pData, // Header data.
|
||
|
AkUInt32 in_uHeaderSize // Size of file package header.
|
||
|
);
|
||
|
|
||
|
// Find a file entry by ID.
|
||
|
const AkFileEntry<AkFileID> * LookupFile(
|
||
|
AkFileID in_uID, // File ID.
|
||
|
AkFileSystemFlags * in_pFlags // Special flags. Do not pass NULL.
|
||
|
);
|
||
|
|
||
|
// Find a file entry by ID with 64 bit ID.
|
||
|
const AkFileEntry<AkUInt64> * LookupFile(
|
||
|
AkUInt64 in_uID, // File ID.
|
||
|
AkFileSystemFlags * in_pFlags // Special flags. Do not pass NULL.
|
||
|
);
|
||
|
|
||
|
// Set current language.
|
||
|
// Returns AK_InvalidLanguage if a package is loaded but the language string cannot be found.
|
||
|
// Returns AK_Success otherwise.
|
||
|
AKRESULT SetCurLanguage(
|
||
|
const AkOSChar* in_pszLanguage // Language string.
|
||
|
);
|
||
|
|
||
|
// Find a soundbank ID by its name (by hashing its name)
|
||
|
AkFileID GetSoundBankID(
|
||
|
const AkOSChar* in_pszBankName // Soundbank name.
|
||
|
);
|
||
|
|
||
|
// Return the id of an external file (by hashing its name in 64 bits)
|
||
|
AkUInt64 GetExternalID(
|
||
|
const AkOSChar* in_pszExternalName // External Source name.
|
||
|
);
|
||
|
|
||
|
protected:
|
||
|
static void RemoveFileExtension( AkOSChar* in_pstring );
|
||
|
static void _MakeLower( AkOSChar* in_pString );
|
||
|
static void _MakeLowerA( char* in_pString, size_t in_strlen );
|
||
|
static AkUInt64 _MakeLowerAndHash64( char* in_pszString );
|
||
|
static AkUInt64 GetID64FromString( const char* in_pszString );
|
||
|
static AkUInt64 GetID64FromString( const wchar_t* in_pszString );
|
||
|
|
||
|
//
|
||
|
// File LUTs.
|
||
|
//
|
||
|
template <class T_FILEID>
|
||
|
class FileLUT
|
||
|
{
|
||
|
public:
|
||
|
const AkFileEntry<T_FILEID> * FileEntries() const { return (AkFileEntry<T_FILEID>*)((AkUInt32*)this + 1); }
|
||
|
bool HasFiles() const { return ( m_uNumFiles > 0 ); }
|
||
|
AkUInt32 NumFiles() const { return m_uNumFiles; }
|
||
|
private:
|
||
|
FileLUT(); // Do not create this object, just cast raw data.
|
||
|
AkUInt32 m_uNumFiles;
|
||
|
};
|
||
|
|
||
|
// Helper: Find a file entry by ID.
|
||
|
template <class T_FILEID>
|
||
|
const AkFileEntry<T_FILEID> * LookupFile(
|
||
|
T_FILEID in_uID, // File ID.
|
||
|
const FileLUT<T_FILEID> * in_pLut, // LUT to search.
|
||
|
bool in_bIsLanguageSpecific // True: match language ID.
|
||
|
);
|
||
|
|
||
|
private:
|
||
|
|
||
|
AkUInt16 m_curLangID; // Current language.
|
||
|
|
||
|
|
||
|
//
|
||
|
// Maps format.
|
||
|
//
|
||
|
class StringMap
|
||
|
{
|
||
|
public:
|
||
|
// Returns AK_INVALID_UNIQUE_ID if ID is not found.
|
||
|
AkUInt32 GetID( const AkOSChar* in_pszString );
|
||
|
inline AkUInt32 GetNumStrings() { return m_uNumStrings; }
|
||
|
private:
|
||
|
struct StringEntry
|
||
|
{
|
||
|
AkUInt32 uOffset; // Byte offset of the string in the packaged strings section,
|
||
|
// from beginning of the string map.
|
||
|
AkUInt32 uID; // ID.
|
||
|
};
|
||
|
StringMap(); // Do not create this object, just cast raw data to use GetID().
|
||
|
AkUInt32 m_uNumStrings;
|
||
|
};
|
||
|
|
||
|
// Languages map.
|
||
|
StringMap * m_pLangMap;
|
||
|
|
||
|
// SoundBanks LUT.
|
||
|
FileLUT<AkFileID> * m_pSoundBanks;
|
||
|
|
||
|
// StreamedFiles LUT.
|
||
|
FileLUT<AkFileID> * m_pStmFiles;
|
||
|
|
||
|
// External Sources LUT.
|
||
|
FileLUT<AkUInt64> * m_pExternals;
|
||
|
};
|
||
|
|
||
|
// Helper: Find a file entry by ID.
|
||
|
template <class T_FILEID>
|
||
|
const CAkFilePackageLUT::AkFileEntry<T_FILEID> * CAkFilePackageLUT::LookupFile(
|
||
|
T_FILEID in_uID, // File ID.
|
||
|
const FileLUT<T_FILEID> * in_pLut, // LUT to search.
|
||
|
bool in_bIsLanguageSpecific // True: match language ID.
|
||
|
)
|
||
|
{
|
||
|
const AkFileEntry<T_FILEID> * pTable = in_pLut->FileEntries();
|
||
|
|
||
|
AKASSERT( pTable && in_pLut->HasFiles() );
|
||
|
AkUInt16 uLangID = in_bIsLanguageSpecific ? m_curLangID : AK_INVALID_LANGUAGE_ID;
|
||
|
|
||
|
// Binary search. LUT items should be sorted by fileID, then by language ID.
|
||
|
AkInt32 uTop = 0, uBottom = in_pLut->NumFiles()-1;
|
||
|
do
|
||
|
{
|
||
|
AkInt32 uThis = ( uBottom - uTop ) / 2 + uTop;
|
||
|
if ( pTable[ uThis ].fileID > in_uID )
|
||
|
uBottom = uThis - 1;
|
||
|
else if ( pTable[ uThis ].fileID < in_uID )
|
||
|
uTop = uThis + 1;
|
||
|
else
|
||
|
{
|
||
|
// Correct ID. Check language.
|
||
|
if ( pTable[ uThis ].uLanguageID > uLangID )
|
||
|
uBottom = uThis - 1;
|
||
|
else if ( pTable[ uThis ].uLanguageID < uLangID )
|
||
|
uTop = uThis + 1;
|
||
|
else
|
||
|
return pTable + uThis;
|
||
|
}
|
||
|
}
|
||
|
while ( uTop <= uBottom );
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
#endif //_AK_FILE_PACKAGE_LUT_H_
|