diff --git a/engine/common/hpak.c b/engine/common/hpak.c index d9be8a68..9a179439 100644 --- a/engine/common/hpak.c +++ b/engine/common/hpak.c @@ -49,6 +49,18 @@ const char *HPAK_TypeFromIndex( int type ) return "?"; } +static inline void HPAK_ResourceToCompat( dresource_t *dest, resource_t *src ) +{ + memcpy( dest, src, sizeof( *dest )); + dest->pNext = dest->pPrev = 0xDEADBEEF; +} + +static inline void HPAK_ResourceFromCompat( resource_t *dest, dresource_t *src ) +{ + memcpy( dest, src, sizeof( *src )); + dest->pNext = dest->pPrev = (void*)0xDEADBEEF; +} + static void HPAK_AddToQueue( const char *name, resource_t *pResource, void *data, file_t *f ) { hash_pack_queue_t *p; @@ -89,6 +101,7 @@ void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *pData, f byte md5[16]; file_t *fout; MD5Context_t ctx; + dresource_t dresource; if( !COM_CheckString( filename )) return; @@ -145,7 +158,7 @@ void HPAK_CreatePak( const char *filename, resource_t *pResource, byte *pData, f hash_pack_info.count = 1; hash_pack_info.entries = Z_Malloc( sizeof( hpak_lump_t )); - hash_pack_info.entries[0].resource = *pResource; + HPAK_ResourceToCompat( &hash_pack_info.entries[0].resource, pResource ); hash_pack_info.entries[0].filepos = FS_Tell( fout ); hash_pack_info.entries[0].disksize = pResource->nDownloadSize; @@ -181,7 +194,7 @@ static qboolean HPAK_FindResource( hpak_info_t *hpk, byte *hash, resource_t *pRe if( !memcmp( hpk->entries[i].resource.rgucMD5_hash, hash, 16 )) { if( pResource ) - *pResource = hpk->entries[i].resource; + HPAK_ResourceFromCompat( pResource, &hpk->entries[i].resource ); return true; } } @@ -330,7 +343,7 @@ void HPAK_AddLump( qboolean bUseQueue, const char *name, resource_t *pResource, memset( pCurrentEntry, 0, sizeof( hpak_lump_t )); FS_Seek( file_dst, hash_pack_header.infotableofs, SEEK_SET ); - pCurrentEntry->resource = *pResource; + HPAK_ResourceToCompat( &pCurrentEntry->resource, pResource ); pCurrentEntry->filepos = FS_Tell( file_dst ); pCurrentEntry->disksize = pResource->nDownloadSize; @@ -370,7 +383,7 @@ static qboolean HPAK_Validate( const char *filename, qboolean quiet ) int i, num_lumps; MD5Context_t MD5_Hash; string pakname; - resource_t *pRes; + dresource_t *pRes; byte md5[16]; if( quiet ) HPAK_FlushHostQueue(); @@ -621,7 +634,7 @@ static qboolean HPAK_ResourceForIndex( const char *filename, int index, resource directory.entries = Z_Malloc( sizeof( hpak_lump_t ) * directory.count ); FS_Read( f, directory.entries, sizeof( hpak_lump_t ) * directory.count ); - *pResource = directory.entries[index-1].resource; + HPAK_ResourceFromCompat( pResource, &directory.entries[index-1].resource ); Z_Free( directory.entries ); FS_Close( f ); diff --git a/engine/common/hpak.h b/engine/common/hpak.h index 4d5c8fde..5e71eec8 100644 --- a/engine/common/hpak.h +++ b/engine/common/hpak.h @@ -37,24 +37,53 @@ infotable dlumpinfo_t[dwadinfo_t->numlumps] #define IDHPAKHEADER (('K'<<24)+('A'<<16)+('P'<<8)+'H') // little-endian "HPAK" #define IDHPAK_VERSION 1 +// a1ba: because Valve for some reason writes resource_t to file +// I had to make it crossplatform version +#pragma pack( push, 8 ) +typedef struct dresource_s +{ + char szFileName[64]; /* 0 64 */ + /* --- cacheline 1 boundary (64 bytes) --- */ + resourcetype_t type; /* 64 4 */ + int nIndex; /* 68 4 */ + int nDownloadSize; /* 72 4 */ + unsigned char ucFlags; /* 76 1 */ + unsigned char rgucMD5_hash[16]; /* 77 16 */ + unsigned char playernum; /* 93 1 */ + unsigned char rguc_reserved[32]; /* 94 32 */ + + /* XXX 2 bytes hole, try to pack */ + + /* --- cacheline 2 boundary (128 bytes) --- */ + uint32_t pNext; /* 128 4 */ + uint32_t pPrev; /* 132 4 */ + + /* size: 136, cachelines: 3, members: 10 */ + /* sum members: 134, holes: 1, sum holes: 2 */ + /* last cacheline: 8 bytes */ +} dresource_t; +#pragma pack( pop ) + +STATIC_ASSERT( sizeof( dresource_t ) == 136, "invalid dresource_t size, HPAKs won't be compatible (no custom logo in multiplayer!)" ); + typedef struct { - int ident; // should be equal HPAK - int version; - int infotableofs; + int ident; // should be equal HPAK + int version; + int infotableofs; } hpak_header_t; typedef struct { - resource_t resource; - int filepos; - int disksize; + dresource_t resource; + int filepos; + int disksize; } hpak_lump_t; typedef struct { - int count; - hpak_lump_t *entries; // variable sized. + int count; + hpak_lump_t *entries; // variable sized. } hpak_info_t; #endif // HPAK_H