From 6ca7271006d99eff37b19c6f3970a9c7c17d5479 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Fri, 24 Apr 2026 20:51:14 +0500 Subject: [PATCH] engine: mod_studio: more studio model swapping --- engine/common/mod_studio.c | 61 ++++++++++++++++++++++++++++++++++++-- public/swaplib.h | 11 +++++++ 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index d133f9b7..c0472ae9 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -162,7 +162,6 @@ le_struct_begin( mstudioattachment_swap ) le_struct_field( mstudioattachment_t, flags ) le_struct_field( mstudioattachment_t, bone ) le_struct_array( mstudioattachment_t, org, 3 ) - le_struct_array( mstudioattachment_t, vectors, 3 * 3 ) le_struct_end(); le_struct_begin( mstudiobodyparts_swap ) @@ -977,6 +976,9 @@ static qboolean Mod_SwapStudioModel( const char *name, void *buffer, size_t buff if( phdr->ident != IDSTUDIOHEADER || phdr->version != STUDIO_VERSION ) return false; + + + #if XASH_BIG_ENDIAN if( phdr->studiohdr2index > 0 && phdr->studiohdr2index < phdr->length ) { @@ -998,7 +1000,11 @@ static qboolean Mod_SwapStudioModel( const char *name, void *buffer, size_t buff le_struct_swap( mstudioseqgroup_swap, (mstudioseqgroup_t *)( mod_base + phdr->seqgroupindex ) + i ); for( int i = 0; i < phdr->numattachments; i++ ) - le_struct_swap( mstudioattachment_swap, (mstudioattachment_t *)( mod_base + phdr->attachmentindex ) + i ); + { + mstudioattachment_t *pattach = (mstudioattachment_t *)( mod_base + phdr->attachmentindex ) + i; + le_struct_swap( mstudioattachment_swap, pattach ); + le_array_swap((float *)pattach->vectors, 3 * 3 ); + } for( int i = 0; i < phdr->numtextures; i++ ) le_struct_swap( mstudiotexture_swap, (mstudiotexture_t *)( mod_base + phdr->textureindex ) + i ); @@ -1013,6 +1019,38 @@ static qboolean Mod_SwapStudioModel( const char *name, void *buffer, size_t buff for( int j = 0; j < pseq->numevents; j++ ) le_struct_swap( mstudioevent_swap, (mstudioevent_t *)( mod_base + pseq->eventindex ) + j ); + + if( pseq->seqgroup != 0 ) + continue; + + mstudioanim_t *panim = (mstudioanim_t *)( mod_base + pseq->animindex ); + int numanims = pseq->numblends * phdr->numbones; + + for( int j = 0; j < numanims; j++, panim++ ) + { + le_struct_swap( mstudioanim_swap, panim ); + + for( int k = 0; k < 6; k++ ) + { + if( panim->offset[k] == 0 ) + continue; + + mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[k] ); + + int frames = pseq->numframes; + while( frames > 0 ) + { + int valid = panimvalue->num.valid; + int total = panimvalue->num.total; + + for( int l = 1; l <= valid; l++ ) + panimvalue[l].value = LittleShort( panimvalue[l].value ); + + panimvalue += valid + 1; + frames -= total; + } + } + } } for( int i = 0; i < phdr->numbodyparts; i++ ) @@ -1024,8 +1062,25 @@ static qboolean Mod_SwapStudioModel( const char *name, void *buffer, size_t buff mstudiomodel_t *pmodel = (mstudiomodel_t *)( mod_base + pbodypart->modelindex ) + j; le_struct_swap( mstudiomodel_swap, pmodel ); + le_array_swap((float *)( mod_base + pmodel->vertindex ), pmodel->numverts * 3 ); + le_array_swap((float *)( mod_base + pmodel->normindex ), pmodel->numnorms * 3 ); + for( int k = 0; k < pmodel->nummesh; k++ ) - le_struct_swap( mstudiomesh_swap, (mstudiomesh_t *)( mod_base + pmodel->meshindex ) + k ); + { + mstudiomesh_t *pmesh = (mstudiomesh_t *)( mod_base + pmodel->meshindex ) + k; + le_struct_swap( mstudiomesh_swap, pmesh ); + + short *ptricmds = (short *)( mod_base + pmesh->triindex ); + short n; + while(( n = LittleShort( *ptricmds ))) + { + *ptricmds++ = n; + int count = abs( n ) * 4; + for( int l = 0; l < count; l++, ptricmds++ ) + *ptricmds = LittleShort( *ptricmds ); + } + *ptricmds = 0; + } } } diff --git a/public/swaplib.h b/public/swaplib.h index dcbddd87..b83123fc 100644 --- a/public/swaplib.h +++ b/public/swaplib.h @@ -82,9 +82,16 @@ static inline void swap_struct_( const swap_struct_def_t *def, size_t len, byte } } +static inline void swap_array_( byte *data, int32_t elem_size, uint32_t count ) +{ + for( uint32_t i = 0; i < count; i++ ) + swap_field_( &data[i * elem_size], elem_size ); +} + // do not use these macros, they will swap structs unconditionally // you might want to use le_/be_ macros instead #define swap_struct( swapdef, ptr ) swap_struct_(( swapdef ), sizeof( swapdef ) / sizeof( swapdef[0] ), (byte *)( ptr )) +#define swap_array( ptr, count ) swap_array_((byte *)( ptr ), sizeof( *( ptr )), ( count )) #define swap_struct_begin( swapdef ) static swap_struct_def_t swapdef[] = { #define swap_struct_end() } @@ -112,6 +119,7 @@ static inline void swap_struct_( const swap_struct_def_t *def, size_t len, byte #define be_struct_array_child( x, y, z, w ) swap_struct_array_child( x, y, z, w ) #define be_struct_end() swap_struct_end() #define be_struct_swap( x, y ) swap_struct( x, y ) + #define be_array_swap( x, y ) swap_array( x, y ) #define le_struct_begin( x ) #define le_struct_field( x, y ) #define le_struct_child( x, y, z ) @@ -119,6 +127,7 @@ static inline void swap_struct_( const swap_struct_def_t *def, size_t len, byte #define le_struct_array_child( x, y, z, w ) #define le_struct_end() extern int _le_struct_end_dummy // define as extern variable, to let end() end with ; #define le_struct_swap( x, y ) (void)(y) + #define le_array_swap( x, y ) (void)(x) #else #define be_struct_begin( x ) #define be_struct_field( x, y ) @@ -127,6 +136,7 @@ static inline void swap_struct_( const swap_struct_def_t *def, size_t len, byte #define be_struct_array_child( x, y, z, w ) #define be_struct_end() extern int _le_struct_end_dummy #define be_struct_swap( x, y ) (void)(y) + #define be_array_swap( x, y ) (void)(x) #define le_struct_begin( x ) swap_struct_begin( x ) #define le_struct_field( x, y ) swap_struct_field( x, y ) #define le_struct_child( x, y, z ) swap_struct_child( x, y, z ) @@ -134,6 +144,7 @@ static inline void swap_struct_( const swap_struct_def_t *def, size_t len, byte #define le_struct_array_child( x, y, z, w ) swap_struct_array_child( x, y, z, w ) #define le_struct_end() swap_struct_end() #define le_struct_swap( x, y ) swap_struct( x, y ) + #define le_array_swap( x, y ) swap_array( x, y ) #endif