Changeset 558

Show
Ignore:
Timestamp:
04/11/08 00:25:14 (9 months ago)
Author:
phill
Message:

o Random loader crap.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/morph-targets/libx42/include/x42.h

    r502 r558  
    316316*/ 
    317317X42_EXPORT x42header_t* X42_CALL x42_LoadHeaderFromBuffer( void *out_buffer, const void **file_data ); 
    318 X42_EXPORT x42header_t* X42_CALL x42_LoadHeaderFromStream( void *out_buffer, x42inStream_t *file_stream ); 
     318//X42_EXPORT x42header_t* X42_CALL x42_LoadHeaderFromStream( void *out_buffer, x42inStream_t *file_stream ); 
    319319 
    320320/* 
     
    339339 
    340340X42_EXPORT x42data_t* X42_CALL x42_LoadDataFromBuffer( void *out_buffer, const x42header_t *h, uint persist_flags, const void *file_data ); 
    341 X42_EXPORT x42data_t* X42_CALL x42_LoadDataFromStream( void *out_buffer, const x42header_t *h, uint persist_flags, x42inStream_t *file_stream ); 
     341//X42_EXPORT x42data_t* X42_CALL x42_LoadDataFromStream( void *out_buffer, const x42header_t *h, uint persist_flags, x42inStream_t *file_stream ); 
    342342 
    343343/*********************************** 
  • branches/morph-targets/libx42/libx42.vcproj

    r500 r558  
    912912                </File> 
    913913                <File 
     914                        RelativePath=".\load-int1.inc.h" 
     915                        > 
     916                </File> 
     917                <File 
     918                        RelativePath=".\load-int2.inc.h" 
     919                        > 
     920                </File> 
     921                <File 
    914922                        RelativePath=".\load.c" 
     923                        > 
     924                        <FileConfiguration 
     925                                Name="Debug (.NET)|Win32" 
     926                                > 
     927                                <Tool 
     928                                        Name="VCCLCompilerTool" 
     929                                        GeneratePreprocessedFile="1" 
     930                                /> 
     931                        </FileConfiguration> 
     932                </File> 
     933                <File 
     934                        RelativePath=".\load_old.c" 
    915935                        > 
    916936                </File> 
     
    10001020                </File> 
    10011021                <File 
     1022                        RelativePath=".\persist-datatypes.inc.h" 
     1023                        > 
     1024                </File> 
     1025                <File 
    10021026                        RelativePath=".\pose.c" 
    10031027                        > 
  • branches/morph-targets/libx42/load.c

    r503 r558  
    3232ALWAYS_INLINE f32 swap_f32( f32 f ) { union { u32 i; f32 f; } u; u.f = f; u.i = swap_u32( u.i ); return u.f; } 
    3333 
    34 X42_EXPORT bool X42_CALL x42_ValidateIdent( const x42Header_ident_t *h ) 
    35 { 
    36 #ifndef LIBX42_NO_PARAM_VALIDATION 
    37         demand_rf( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." )
    38 #endif 
    39  
    40        if( h->ident != X42_IDENT
    41                 return false; 
    42  
    43         switch( h->version ) 
    44         { 
    45         case X42_VER_V5: 
    46         case X42_VER_V6: 
    47                 break;     
    48  
    49         default: 
    50                 return false; 
     34typedef struct bufSrc_t 
     35{ 
     36        byte                    *buf; 
     37        size_t                 pos
     38} bufSrc_t; 
     39 
     40static bool align_buf_ptr( bufSrc_t *src, size_t a
     41
     42        if( a ) 
     43        { 
     44               size_t ofs = ((a - (src->pos % a)) % a); 
     45 
     46               if( ofs ) 
     47                { 
     48                        src->buf += ofs; 
     49                       src->pos += ofs; 
     50                } 
    5151        } 
    5252 
     
    5454} 
    5555 
    56 X42_EXPORT bool X42_CALL x42_ValidateHeader( const x42header_t *h ) 
    57 
    58 #ifndef LIBX42_NO_PARAM_VALIDATION 
    59         demand_rf( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." ); 
    60 #endif 
    61  
    62         if( !x42_ValidateIdent( &h->ident ) ) 
    63                 return false; 
    64  
    65         return true; 
    66 
    67  
    68 typedef struct bufStm_t 
    69 
    70         const byte              *pBuf; 
    71         size_t                  cbRead; 
    72 } bufStm_t; 
    73  
    74 static size_t X42_CALL bufStm_read( void *buffer, size_t cb, void *baton ) 
    75 
    76         bufStm_t *s = (bufStm_t*)baton; 
    77  
    78         memcpy( buffer, s->pBuf, cb ); 
    79  
    80         s->pBuf += cb; 
    81         s->cbRead += cb; 
    82  
    83         return cb; 
    84 
    85  
    86 static size_t read_n( void *buffer, size_t cb, x42inStream_t *file_stream ) 
     56typedef struct stmSrc_t 
     57
     58        x42inStream_t   stm; 
     59        size_t                  pos; 
     60} stmSrc_t; 
     61 
     62static size_t read_n( void *buffer, size_t cb, stmSrc_t *source ) 
    8763{ 
    8864        byte *buf = (byte*)buffer; 
     
    9167        while( cb ) 
    9268        { 
    93                 size_t cr = file_stream->read_fn( buf, cb, file_stream->baton ); 
     69                size_t cr = source->stm.read_fn( buf, cb, source->stm.baton ); 
    9470 
    9571                demand_rv( cr <= cb, X42_ERR_BADSTREAM, "stream returned more data than requested", cbRead ); 
     
    10278        } 
    10379 
     80        source->pos += cbRead; 
    10481        return cbRead; 
    10582} 
    10683 
    107 static bool align_stream( x42inStream_t *file_stream, size_t *pos, size_t a ) 
    108 
     84static bool align_stream( stmSrc_t *src, size_t a ) 
     85
     86        byte tmp[128]; 
     87        assert( a < sizeof( tmp ), X42_ERR_INTERNAL, "crazy huge alignment value" ); 
     88 
    10989        if( a ) 
    11090        { 
    111                 size_t ofs = ((a - (*pos % a)) % a); 
    112                  
    113 #ifdef LIBX42_NO_ALLOCA 
    114                 byte tmp[128]; 
    115                  
    116                 assert( a < sizeof( tmp ), X42_ERR_INTERNAL, "crazy huge alignment value" ); 
    117 #else 
    118                 byte *tmp = ofs ? (byte*)_alloca( ofs ) : NULL; 
    119 #endif 
     91                size_t ofs = ((a - (src->pos % a)) % a); 
    12092 
    12193                if( ofs ) 
    122                         *pos += read_n( tmp, ofs, file_stream ); 
    123  
    124                 demand_rf( *pos % a == 0, X42_ERR_INTERNAL, "failed to align stream - EOF?" ); 
    125         } 
     94                        src->pos += read_n( tmp, ofs, src ); 
     95 
     96                demand_rf( src->pos % a == 0, X42_ERR_INTERNAL, "failed to align stream - EOF?" ); 
     97        } 
     98 
    12699        return true; 
    127100} 
    128101 
    129 static bool read_packed_floats( x42inStream_t *file_stream, size_t *inPos, 
    130         const vec2_t *bounds, uint components, float *dest, uint elements, 
    131         size_t elemStride ) 
    132 
    133         uint i; 
    134         float scale[4], bias[4]; 
    135         size_t cbElem; 
    136  
    137         if( !elements ) 
    138                 return true; 
    139  
    140         for( i = 0; i < components; i++ ) 
    141         { 
    142                 bias[i] = bounds[i][0]; 
    143                 scale[i] = (bounds[i][1] - bounds[i][0]) / 65530.0F; 
    144         } 
    145  
    146         cbElem = sizeof( u16 ) * components; 
    147  
    148         for( i = 0; i < elements; i++ ) 
    149         { 
    150                 uint c; 
    151                 u16 buf[4]; 
    152  
    153                 if( read_n( buf, cbElem, file_stream ) != cbElem ) 
    154                         return false; 
    155  
    156                 for( c = 0; c < components; c++ ) 
    157                         dest[c] = buf[c] * scale[c] + bias[c]; 
    158  
    159                 dest = (float*)((byte*)dest + elemStride); 
    160         } 
    161  
    162         *inPos += cbElem * elements; 
    163         return true; 
    164 
    165  
    166 static bool read_packed_floats_swp( x42inStream_t *file_stream, size_t *inPos, 
    167         const vec2_t *bounds, uint components, float *dest, uint elements, 
    168         size_t elemStride ) 
    169 
    170         uint i; 
    171         float scale[4], bias[4]; 
    172         size_t cbElem; 
    173  
    174         if( !elements ) 
    175                 return true; 
    176  
    177         for( i = 0; i < components; i++ ) 
    178         { 
    179                 bias[i] = bounds[i][0]; 
    180                 scale[i] = (bounds[i][1] - bounds[i][0]) / 65530.0F; 
    181         } 
    182  
    183         cbElem = sizeof( u16 ) * components; 
    184  
    185         for( i = 0; i < elements; i++ ) 
    186         { 
    187                 uint c; 
    188                 u16 buf[4]; 
    189  
    190                 if( read_n( buf, cbElem, file_stream ) != cbElem ) 
    191                         return false; 
    192  
    193                 for( c = 0; c < components; c++ ) 
    194                         dest[c] = (float)(int)swap_u16( buf[c] ) * scale[c] + bias[c]; 
    195  
    196                 dest = (float*)((byte*)dest + elemStride); 
    197         } 
    198  
    199         *inPos += cbElem * elements; 
    200         return true; 
    201 
    202  
    203 static bool read_packed_floats_s16n( x42inStream_t *file_stream, size_t *inPos, 
    204         uint components, float *dest, uint elements, 
    205         size_t elemStride ) 
    206 
    207         uint i; 
    208         size_t cbElem; 
    209  
    210         if( !elements ) 
    211                 return true; 
    212  
    213         cbElem = sizeof( s16 ) * components; 
    214  
    215         for( i = 0; i < elements; i++ ) 
    216         { 
    217                 uint c; 
    218                 s16 buf[4]; 
    219  
    220                 if( read_n( buf, cbElem, file_stream ) != cbElem ) 
    221                         return false; 
    222  
    223                 for( c = 0; c < components; c++ ) 
    224                         dest[c] = X42_FLOAT_S16N_UNPACK( buf[c] ); 
    225  
    226                 dest = (float*)((byte*)dest + elemStride); 
    227         } 
    228  
    229         *inPos += cbElem * elements; 
    230         return true; 
    231 
    232  
    233 static bool read_packed_floats_s16n_swp( x42inStream_t *file_stream, size_t *inPos, 
    234         uint components, float *dest, uint elements, 
    235         size_t elemStride ) 
    236 
    237         uint i; 
    238         size_t cbElem; 
    239  
    240         if( !elements ) 
    241                 return true; 
    242  
    243         cbElem = sizeof( s16 ) * components; 
    244  
    245         for( i = 0; i < elements; i++ ) 
    246         { 
    247                 uint c; 
    248                 s16 buf[4]; 
    249  
    250                 if( read_n( buf, cbElem, file_stream ) != cbElem ) 
    251                         return false; 
    252  
    253                 for( c = 0; c < components; c++ ) 
    254                         dest[c] = X42_FLOAT_S16N_UNPACK( swap_s16( buf[c] ) ); 
    255  
    256                 dest = (float*)((byte*)dest + elemStride); 
    257         } 
    258  
    259         *inPos += cbElem * elements; 
    260         return true; 
    261 
    262  
    263 static bool read_packed_floats_s8n( x42inStream_t *file_stream, size_t *inPos, 
    264         uint components, float *dest, uint elements, 
    265         size_t elemStride ) 
    266 
    267         uint i; 
    268         size_t cbElem; 
    269  
    270         if( !elements ) 
    271                 return true; 
    272  
    273         cbElem = sizeof( s8 ) * components; 
    274  
    275         for( i = 0; i < elements; i++ ) 
    276         { 
    277                 uint c; 
    278                 s8 buf[8]; 
    279  
    280                 if( read_n( buf, cbElem, file_stream ) != cbElem ) 
    281                         return false; 
    282  
    283                 for( c = 0; c < components; c++ ) 
    284                         dest[c] = X42_FLOAT_S8N_UNPACK( buf[c] ); 
    285  
    286                 dest = (float*)((byte*)dest + elemStride); 
    287         } 
    288  
    289         *inPos += cbElem * elements; 
    290         return true; 
    291 
    292  
    293 #define read_packed_floats_s8n_swp read_packed_floats_s8n 
    294  
    295 static bool skip_block( x42inStream_t *file_stream, size_t cb ) 
     102static bool skip_block( stmSrc_t *src, size_t cb ) 
    296103{ 
    297104        size_t len; 
     
    307114                        len = sizeof( tmp ); 
    308115 
    309                 cbR = read_n( tmp, cbRq, file_stream ); 
     116                cbR = read_n( tmp, cbRq, src ); 
    310117 
    311118                demand_rf( cbR != 0, X42_ERR_INTERNAL, "failed to skip stream bytes - EOF?" ); 
     
    315122 
    316123        return true; 
     124} 
     125 
     126/******************************************************** 
     127        Swapped/Unswapped loader routines. 
     128 
     129        Functions that vary only by whether they swap or not 
     130        are defined in load-int1.inc. 
     131 
     132        This file is included twice, once for unswapped 
     133        reading, and once for swapped. The macros around the 
     134        include site define the behavior. 
     135********************************************************/ 
     136 
     137#define read_s16( l ) (l) 
     138#define read_u16( l ) (l) 
     139#define read_u32( l ) (l) 
     140#define read_f32( f ) (f) 
     141 
     142#define SWP_EXT dir 
     143 
     144#include "load-int1.inc.h" 
     145 
     146#undef SWP_EXT 
     147 
     148#undef read_f32 
     149#undef read_u32 
     150#undef read_u16 
     151#undef read_s16 
     152 
     153#define read_s16( l ) swap_s16( l ) 
     154#define read_u16( l ) swap_u16( l ) 
     155#define read_u32( l ) swap_u32( l ) 
     156#define read_f32( f ) swap_f32( f ) 
     157 
     158#define SWP_EXT swp 
     159 
     160#include "load-int1.inc.h" 
     161 
     162#undef SWP_EXT 
     163 
     164#undef read_f32 
     165#undef read_u32 
     166#undef read_u16 
     167#undef read_s16 
     168 
     169X42_EXPORT bool X42_CALL x42_ValidateIdent( const x42Header_ident_t *h ) 
     170{ 
     171#ifndef LIBX42_NO_PARAM_VALIDATION 
     172        demand_rf( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." ); 
     173#endif 
     174 
     175        if( h->ident != X42_IDENT ) 
     176                return false; 
     177 
     178        switch( h->version ) 
     179        { 
     180        case X42_VER_V5: 
     181        case X42_VER_V6: 
     182                break;      
     183 
     184        default: 
     185                return false; 
     186        } 
     187 
     188        return true; 
     189} 
     190 
     191X42_EXPORT bool X42_CALL x42_ValidateHeader( const x42header_t *h ) 
     192{ 
     193#ifndef LIBX42_NO_PARAM_VALIDATION 
     194        demand_rf( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." ); 
     195#endif 
     196 
     197        if( !x42_ValidateIdent( &h->ident ) ) 
     198                return false; 
     199 
     200        return true; 
     201} 
     202 
     203/* 
     204        The actual loader functions follow. 
     205         
     206        The out_buffer parameter must point to a buffer that is at least x42_GetLoadedSize bytes long. 
     207        The h parameter points to the x42 file's header. 
     208 
     209        The last parameter is a mechanism to get all of the file data that follows the header. So if 
     210        you're passing in a stream it should be seeked to sizeof( x42Header_t ) bytes into the file. 
     211 
     212        Freeing the file is simple: just free the buffer you passed in and it's gone. All of the data associated 
     213        with an in-memory x42 file is stored in that buffer. 
     214 
     215        These functions will return NULL if they fail. 
     216*/ 
     217X42_EXPORT x42data_t* X42_CALL x42_LoadDataFromStream( void *out_buffer, const x42header_t *h, 
     218        uint persist_flags, x42inStream_t *file_stream ) 
     219{ 
     220        bool stat; 
     221        x42data_t *ret; 
     222        size_t inPos; 
     223 
     224#ifndef LIBX42_NO_PARAM_VALIDATION 
     225        demand_rn( out_buffer != NULL, X42_ERR_BADPTR, "out_buffer is NULL" ); 
     226        demand_rn( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." ); 
     227        demand_rn( x42_ValidateHeader( h ), X42_ERR_BADDATA, "Invalid x42 file header." ); 
     228        demand_rn( file_stream != NULL, X42_ERR_BADPTR, "file_stream is NULL" ); 
     229        demand_rn( file_stream->read_fn != NULL, X42_ERR_BADSTREAM, "file_stream has a NULL read_fn" ); 
     230#endif 
     231 
     232        ret = x42_SetupBufferPointers( out_buffer, h, persist_flags ); 
     233        demand_rn( ret != NULL, X42_ERR_INTERNAL, "failed to set up buffer pointers" ); 
     234 
     235        inPos = sizeof( x42Header_ident_t ); 
     236        switch( h->ident.version ) 
     237        { 
     238        case X42_VER_V5: 
     239                inPos += sizeof( x42Header_v5_t ); 
     240                break; 
     241 
     242        case X42_VER_V6: 
     243                inPos += sizeof( x42Header_v6_t ); 
     244                break; 
     245 
     246        default: 
     247                fail_rn( X42_ERR_INTERNAL, "invalid file version" ); 
     248        } 
     249 
     250        if( h->runFlags & X42_RF_LOAD_SWAPPED ) 
     251        { 
     252                stat = load_swapped( ret, h, file_stream, inPos ); 
     253        } 
     254        else 
     255        { 
     256                stat = load_direct( ret, h, file_stream, inPos ); 
     257        } 
     258 
     259        demand_rn( stat, X42_ERR_INTERNAL, "failed to load file data" ); 
     260 
     261        return ret; 
    317262} 
    318263 
     
    507452} 
    508453 
    509 static void fixup_persist_flags( uint *pf, const x42header_t *h ) 
    510 { 
    511         if( !(h->modelFlags & X42_MF_HAS_NORMALS) ) 
    512                 *pf &= ~X42_PERSIST_NORMALS; 
    513         if( !(h->modelFlags & X42_MF_HAS_TANGENT_BASIS) ) 
    514                 *pf &= ~X42_PERSIST_TANGENT_BASIS; 
    515         if( !(h->modelFlags &X42_MF_HAS_TEXTURE_COORDINATES) ) 
    516                 *pf &= ~X42_PERSIST_TEXTURE_COORDINATES; 
    517         if( !(h->modelFlags & X42_MF_HAS_COLORS) ) 
    518                 *pf &= ~X42_PERSIST_COLORS; 
    519 } 
    520  
    521 //get the size of buffer a given x42 file (represented by its header) will use in memory 
    522 X42_EXPORT size_t X42_CALL x42_GetLoadedSize( const x42header_t *h, uint persist_flags ) 
    523 { 
    524         size_t ret; 
    525  
    526 #ifndef LIBX42_NO_PARAM_VALIDATION 
    527         demand_rz( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." ); 
    528         demand_rz( x42_ValidateHeader( h ), X42_ERR_BADDATA, "Invalid x42 file header." ); 
    529 #endif 
    530  
    531         fixup_persist_flags( &persist_flags, h ); 
    532  
    533         ret = sizeof( x42data_t ); 
    534  
    535         /* 
    536                 The x42data_t struct always resides at the start 
    537                 of the buffer. Sneak in 16 bytes so that the buffer 
    538                 pointer can be pushed to a 16-byte boundary before 
    539                 we lay out the rest of the data. 
    540         */ 
    541         ret += sizeof( float[4] ); 
    542  
    543         ret = align( ret, sizeof( void* ) )                     + sizeof( x42keyStreamEntry_t )         * h->keyStreamLength; 
    544         ret = align( ret, sizeof( void* ) )                     + sizeof( x42animation_t )                      * h->numAnims; 
    545          
    546         ret = align( ret, sizeof( float ) )                     + sizeof( vec3_t )                                      * h->numPosValues; 
    547         ret = align( ret, sizeof( float ) )                     + sizeof( vec3_t )                                      * h->numScaleValues; 
    548         ret = align( ret, sizeof( float ) )                     + sizeof( quat_t )                                      * h->numRotValues; 
    549          
    550         ret = align( ret, sizeof( void* ) )                     + sizeof( x42animGroup_t )                      * h->numAnimGroups; 
    551         ret = align( ret, sizeof( void* ) )                     + sizeof( x42bone_t )                           * h->numBones; 
    552         ret = align( ret, sizeof( void* ) )                     + sizeof( u8 )                                          * h->numBones; 
    553          
    554         ret = align( ret, sizeof( void* ) )                     + sizeof( x42influence_t )                      * h->numInfluences; 
    555         ret = align( ret, sizeof( void* ) )                     + sizeof( x42tag_t )                            * h->numTags; 
    556          
    557         ret = align( ret, sizeof( void* ) )                     + sizeof( x42lodRange_t )                       * h->numLods; 
    558         ret = align( ret, sizeof( void* ) )                     + sizeof( x42group_t )                          * h->numGroups; 
    559         ret = align( ret, sizeof( void* ) )                     + sizeof( x42morphTarget_t )            * h->numMorphTargets; 
    560          
    561         ret = align( ret, sizeof( float[4] ) )          + sizeof( x42vertAnim_t )                       * h->numVerts; 
    562         if( persist_flags & X42_PERSIST_NORMALS ) 
    563                 ret = align( ret, sizeof( float[4] ) )  + sizeof( x42vertNormal_t )                     * h->numVerts; 
    564         if( persist_flags & X42_PERSIST_TANGENT_BASIS ) 
    565                 ret = align( ret, sizeof( float[4] ) )  + sizeof( x42vertTangent_t )            * h->numVerts; 
    566         if( persist_flags & X42_PERSIST_TEXTURE_COORDINATES ) 
    567                 ret = align( ret, sizeof( float ) )             + sizeof( vec2_t )                                      * h->numVerts; 
    568         if( persist_flags & X42_PERSIST_COLORS ) 
    569                 ret = align( ret, sizeof( rgba_t ) )    + sizeof( rgba_t )                                      * h->numVerts; 
    570  
    571         ret = align( ret, sizeof( x42index_t ) )        + sizeof( x42index_t )                          * h->numIndices; 
    572          
    573         ret = align( ret, sizeof( x42index_t ) )        + sizeof( x42index_t )                          * h->numMorphDeltas; 
    574         ret = align( ret, sizeof( float[4] ) )          + sizeof( vec4_t )                                      * h->numMorphDeltas; 
    575         if( persist_flags & X42_PERSIST_NORMALS ) 
    576                 ret = align( ret, sizeof( float[4] ) )  + sizeof( x42morphNormal_t )            * h->numMorphDeltas; 
    577         if( persist_flags & X42_PERSIST_TANGENT_BASIS ) 
    578                 ret = align( ret, sizeof( float[4] ) )  + sizeof( x42morphTangent_t )           * h->numMorphDeltas; 
    579  
    580         ret += sizeof( char ) * h->nameBlobLen; 
    581  
    582         return ret; 
    583 } 
    584  
    585 ALWAYS_INLINE void* advance_out_internal( byte **out, size_t a, size_t cb ) 
    586 { 
    587         void *ret; 
    588  
    589         *out = align_ptr( *out, a ); 
    590         ret = *out; 
    591  
    592         *out += cb; 
    593  
    594         return ret; 
    595 } 
    596  
    597 X42_EXPORT x42data_t* X42_CALL x42_SetupBufferPointers( void *out_buffer, const x42header_t *h, uint persist_flags ) 
    598 { 
    599         byte *out; 
    600         x42data_t *ret; 
    601  
    602 #ifndef LIBX42_NO_PARAM_VALIDATION 
    603         demand_rn( out_buffer != NULL, X42_ERR_BADPTR, "out_buffer is NULL" ); 
    604         demand_rn( h != NULL, X42_ERR_BADPTR, "Expected valid x42Header pointer, got NULL instead." ); 
    605         demand_rn( x42_ValidateHeader( h ), X42_ERR_BADDATA, "Invalid x42 file header." ); 
    606 #endif 
    607  
    608         fixup_persist_flags( &persist_flags, h ); 
    609  
    610 #define advance_out( a, cb ) advance_out_internal( &out, a, cb ) 
    611  
    612         ret = (x42data_t*)out_buffer; 
    613         memcpy( &ret->header, h, sizeof( x42header_t ) ); 
    614  
    615         out = (byte*)(ret + 1); 
    616         out = align_ptr( out, sizeof( float[4] ) ); 
    617  
    618         ret->keyStream          = (x42keyStreamEntry_t*)advance_out( sizeof( void* ),   sizeof( x42keyStreamEntry_t )*h->keyStreamLength ); 
    619         ret->animations         = (x42animation_t*)             advance_out( sizeof( void* ),   sizeof( x42animation_t )        * h->numAnims ); 
    620  
    621         ret->posValues          = (vec3_t*)                             advance_out( sizeof( float ),   sizeof( vec3_t )                        * h->numPosValues ); 
    622         ret->scaleValues        = (vec3_t*)                             advance_out( sizeof( float ),   sizeof( vec3_t )                        * h->numScaleValues ); 
    623         ret->rotValues          = (quat_t*)                             advance_out( sizeof( float ),   sizeof( quat_t )                        * h->numRotValues ); 
    624  
    625         ret->animGroups         = (x42animGroup_t*)             advance_out( sizeof( void* ),   sizeof( x42animGroup_t )        * h->numAnimGroups ); 
    626         ret->bones                      = (x42bone_t*)                  advance_out( sizeof( void* ),   sizeof( x42bone_t )                     * h->numBones ); 
    627         ret->boneGroups         = (u8*)                                 advance_out( sizeof( void* ),   sizeof( u8 )                            * h->numBones ); 
    628  
    629         ret->influences         = (x42influence_t*)             advance_out( sizeof( void* ),   sizeof( x42influence_t )        * h->numInfluences ); 
    630         ret->tags                       = (x42tag_t*)                   advance_out( sizeof( void* ),   sizeof( x42tag_t )                      * h->numTags ); 
    631  
    632         ret->lods                       = (x42lodRange_t*)              advance_out( sizeof( void* ),   sizeof( x42lodRange_t )         * h->numLods ); 
    633         ret->groups                     = (x42group_t*)                 advance_out( sizeof( void* ),   sizeof( x42group_t )            * h->numGroups ); 
    634         ret->morphTargets       = (x42morphTarget_t*)   advance_out( sizeof( void* ),   sizeof( x42morphTarget_t )      * h->numMorphTargets ); 
    635  
    636         ret->vertPos            = (x42vertAnim_t*)              advance_out( sizeof( float[4] ),sizeof( x42vertAnim_t )         * h->numVerts ); 
    637  
    638         if( persist_flags & X42_PERSIST_NORMALS ) 
    639                 ret->vertNorm   = (x42vertNormal_t*)    advance_out( sizeof( float[4] ),sizeof( x42vertNormal_t )       * h->numVerts ); 
    640         else 
    641                 ret->vertNorm = NULL; 
    642  
    643         if( persist_flags & X42_PERSIST_TANGENT_BASIS ) 
    644                 ret->vertTan    = (x42vertTangent_t*)   advance_out( sizeof( float[4] ),sizeof( x42vertTangent_t )      * h->numVerts ); 
    645         else 
    646                 ret->vertTan = NULL; 
    647  
    648         if( persist_flags & X42_PERSIST_TEXTURE_COORDINATES ) 
    649                 ret->vertTc = (vec2_t*)                                 advance_out( sizeof( float ),           sizeof( vec2_t )                        * h->numVerts ); 
    650         else 
    651                 ret->vertTc = NULL; 
    652  
    653         if( persist_flags & X42_PERSIST_COLORS ) 
    654                 ret->vertCl = (rgba_t*)                                 advance_out( sizeof( rgba_t ),          sizeof( rgba_t )                        * h->numVerts ); 
    655         else 
    656                 ret->vertCl = NULL; 
    657  
    658         ret->indices = (x42index_t*)                            advance_out( sizeof( x42index_t ),      sizeof( x42index_t )            * h->numIndices ); 
    659  
    660         ret->morphIndices       = (x42index_t*)                 advance_out( sizeof( x42index_t ),      sizeof( x42index_t )            * h->numMorphDeltas ); 
    661         ret->morphPos           = (vec4_t*)                             advance_out( sizeof( float[4] ),        sizeof( vec4_t )                        * h->numMorphDeltas ); 
    662  
    663         if( persist_flags & X42_PERSIST_NORMALS ) 
    664                 ret->morphNorm  = (x42morphNormal_t*)   advance_out( sizeof( float[4] ),        sizeof( x42morphNormal_t )      * h->numMorphDeltas ); 
    665         else 
    666                 ret->morphNorm = NULL; 
    667  
    668         if( persist_flags & X42_PERSIST_TANGENT_BASIS ) 
    669                 ret->morphTan   = (x42morphTangent_t*)  advance_out( sizeof( float[4] ),        sizeof( x42morphTangent_t )     * h->numMorphDeltas ); 
    670         else 
    671                 ret->morphTan = NULL; 
    672  
    673         ret->strings = (char*)                                          advance_out( sizeof( char ),            sizeof( char )                          * h->nameBlobLen ); 
    674  
    675         return ret; 
    676 } 
    677  
    678 X42_EXPORT x42data_t* x42_CopyRuntimeData( void *out_buffer, const x42data_t *src ) 
    679 { 
    680         uint persist_flags; 
    681         const x42header_t *h; 
    682         x42data_t *ret; 
    683          
    684         x42data_t tmp; 
    685  
    686 #ifndef LIBX42_NO_PARAM_VALIDATION 
    687         demand_rn( out_buffer != NULL, X42_ERR_BADPTR, "out_buffer is NULL" ); 
    688         demand_rn( src != NULL, X42_ERR_BADPTR, "Expected valid x42data_t pointer, got NULL instead." ); 
    689 #endif 
    690  
    691         //src may be unaligned - copy it to stack before reading anything from it 
    692         memcpy( &tmp, src, sizeof( x42data_t ) ); 
    693         src = &tmp; 
    694  
    695 #ifndef LIBX42_NO_PARAM_VALIDATION 
    696         demand_rn( x42_ValidateHeader( &src->header ), X42_ERR_BADDATA, "Invalid x42 file header." ); 
    697 #endif 
    698  
    699         h = &src->header; 
    700  
    701         persist_flags = 0; 
    702         if( src->vertNorm ) 
    703                 persist_flags |= X42_PERSIST_NORMALS; 
    704         if( src->vertTan ) 
    705                 persist_flags |= X42_PERSIST_TANGENT_BASIS; 
    706         if( src->vertTc ) 
    707                 persist_flags |= X42_PERSIST_TEXTURE_COORDINATES; 
    708         if( src->vertCl ) 
    709                 persist_flags |= X42_PERSIST_COLORS; 
    710  
    711         ret = x42_SetupBufferPointers( out_buffer, h, persist_flags ); 
    712  
    713         memcpy( ret->keyStream,         src->keyStream,         sizeof( x42keyStreamEntry_t )   * h->keyStreamLength ); 
    714         memcpy( ret->animations,        src->animations,        sizeof( x42animation_t )                * h->numAnims ); 
    715          
    716         memcpy( ret->posValues,         src->posValues,         sizeof( vec3_t )                                * h->numPosValues ); 
    717         memcpy( ret->scaleValues,       src->scaleValues,       sizeof( vec3_t )                                * h->numScaleValues ); 
    718         memcpy( ret->rotValues,         src->rotValues,         sizeof( quat_t )                                * h->numRotValues ); 
    719  
    720         memcpy( ret->animGroups,        src->animGroups,        sizeof( x42animGroup_t )                * h->numAnimGroups ); 
    721         memcpy( ret->bones,                     src->bones,                     sizeof( x42bone_t )                             * h->numBones ); 
    722         memcpy( ret->boneGroups,        src->boneGroups,        sizeof( u8 )                                    * h->numBones ); 
    723          
    724         memcpy( ret->influences,        src->influences,        sizeof( x42influence_t )                * h->numInfluences ); 
    725         memcpy( ret->tags,                      src->tags,                      sizeof( x42tag_t )                              * h->numTags ); 
    726  
    727         memcpy( ret->lods,                      src->lods,                      sizeof( x42lodRange_t )                 * h->numLods ); 
    728         memcpy( ret->groups,            src->groups,            sizeof( x42group_t )                    * h->numGroups ); 
    729         memcpy( ret->morphTargets,      src->morphTargets,      sizeof( x42morphTarget_t )              * h->numMorphTargets ); 
    730  
    731         memcpy( ret->vertPos,           src->vertPos,           sizeof( x42vertAnim_t )                 * h->numVerts ); 
    732          
    733         if( src->vertNorm ) 
    734                 memcpy( ret->vertNorm,  src->vertNorm,          sizeof( x42vertNormal_t )               * h->numVerts ); 
    735  
    736         if( src->vertTan ) 
    737                 memcpy( ret->vertTan,   src->vertTan,           sizeof( x42vertTangent_t )              * h->numVerts ); 
    738  
    739         if( src->vertTc ) 
    740                 memcpy( ret->vertTc,    src->vertTc,            sizeof( vec2_t )                                * h->numVerts ); 
    741  
    742         if( src->vertCl ) 
    743                 memcpy( ret->vertCl,    src->vertCl,            sizeof( rgba_t )                                * h->numVerts ); 
    744  
    745         memcpy( ret->indices,           src->indices,           sizeof( x42index_t )                    * h->numIndices ); 
    746  
    747         memcpy( ret->morphIndices,      src->morphIndices,      sizeof( x42index_t )                    * h->numMorphDeltas ); 
    748         memcpy( ret->morphPos,          src->morphPos,          sizeof( vec4_t )                                * h->numMorphDeltas ); 
    749  
    750         if( src->morphNorm ) 
    751                 memcpy( ret->morphNorm, src->morphNorm,         sizeof( x42morphNormal_t )              * h->numMorphDeltas ); 
    752  
    753         if( src->morphTan ) 
    754                 memcpy( ret->morphTan,  src->morphTan,          sizeof( x42morphTangent_t )             * h->numMorphDeltas ); 
    755  
    756         memcpy( CONST_CAST( char, ret->strings ), src->strings,         sizeof( char )          * h->nameBlobLen ); 
    757  
    758         return ret; 
    759 } 
    760  
    761 static bool load_direct( x42data_t *ret, const x42header_t *h, 
    762         x42inStream_t *file_stream, size_t inPos ) 
    763 { 
    764         uint i; 
    765  
    766         bool stat; 
    767         x42PackHeader_v6_t pack; 
    768  
    769         /* 
    770                 Stream read helper macros begin here... 
    771         */ 
    772  
    773 #define read_check() demand_rf( stat, X42_ERR_INTERNAL, "failed to read from stream" ) 
    774  
    775 #define checked_read( buf, type, count )                                                                        \ 
    776         if( const_cond_true )                                                                                                   \ 
    777         {                                                                                                                                               \ 
    778                 size_t cb = sizeof( type ) * count;                                                                     \ 
    779                 stat = read_n( buf, cb, file_stream ) == cb;                                            \ 
    780                                                                                                                                                         \ 
    781                 read_check();                                                                                                           \ 
    782                 inPos += cb;                                                                                                            \ 
    783         }                                                                                                                                               \ 
    784         else                                                                                                                                    \ 
    785                 (void)0 
    786  
    787 #define checked_align( a )                                                                                                      \ 
    788         if( const_cond_true )                                                                                                   \ 
    789         {                                                                                                                                               \ 
    790                 stat = align_stream( file_stream, &inPos, a );                                          \ 
    791                 demand_rf( stat, X42_ERR_INTERNAL, "failed to align stream" );          \ 
    792         }                                                                                                                                               \ 
    793         else                                                                                                                                    \ 
    794                 (void)0 
    795  
    796 #define checked_read_a( buf, type, count, a )                                                           \ 
    797         if( const_cond_true )                                                                                                   \ 
    798         {                                                                                                                                               \ 
    799                 checked_align( a );                                                                                                     \ 
    800                 checked_read( buf, type, count );                                                                       \ 
    801         }                                                                                                                                               \ 
    802         else                                                                                                                                    \ 
    803                 (void)0 
    804  
    805 #define checked_read_packed_floats( buf, pack, comps, count, stride )           \ 
    806         if( const_cond_true )                                                                                                   \ 
    807         {                        &nbs