int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist, lwPolygonList *plist ){ unsigned int type; int rlen = 0, i, j; set_flen( 0 ); type = getU4( fp ); rlen = get_flen(); if ( rlen < 0 ) { return 0; } if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) { _pico_memstream_seek( fp, cksize - 4, PICO_SEEK_CUR ); return 1; } while ( rlen < cksize ) { i = getVX( fp ) + plist->offset; j = getVX( fp ) + tlist->offset; rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) { return 0; } switch ( type ) { case ID_SURF: plist->pol[ i ].surf = ( lwSurface * ) ( (size_t)j ); break; case ID_PART: plist->pol[ i ].part = j; break; case ID_SMGP: plist->pol[ i ].smoothgrp = j; break; } } return 1; }
int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ) { unsigned int id, formsize, type; /* open the file */ if ( !fp ) return PICO_PMV_ERROR_MEMORY; /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { return PICO_PMV_ERROR_SIZE; } /* LWOB? */ if ( id != ID_FORM || type != ID_LWOB ) { if ( failpos ) *failpos = 12; return PICO_PMV_ERROR_IDENT; } return PICO_PMV_OK; }
int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist ){ char *buf, *bp; int i, len, ntags; if ( cksize == 0 ) { return 1; } /* read the whole chunk */ set_flen( 0 ); buf = getbytes( fp, cksize ); if ( !buf ) { return 0; } /* count the strings */ ntags = 0; bp = buf; while ( bp < buf + cksize ) { len = strlen( bp ) + 1; len += len & 1; bp += len; ++ntags; } /* expand the string array to hold the new tags */ tlist->offset = tlist->count; tlist->count += ntags; if ( !_pico_realloc( (void *) &tlist->tag, ( tlist->count - ntags ) * sizeof( char * ), tlist->count * sizeof( char * ) ) ) { goto Fail; } memset( &tlist->tag[ tlist->offset ], 0, ntags * sizeof( char * ) ); /* copy the new tags to the tag array */ bp = buf; for ( i = 0; i < ntags; i++ ) tlist->tag[ i + tlist->offset ] = sgetS0( &bp ); _pico_free( buf ); return 1; Fail: if ( buf ) { _pico_free( buf ); } return 0; }
lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type ) { lwTexture *tex; unsigned short sz; int ok; tex = _pico_calloc( 1, sizeof( lwTexture ) ); if ( !tex ) { return NULL; } tex->type = type; tex->tmap.size.val[ 0 ] = tex->tmap.size.val[ 1 ] = tex->tmap.size.val[ 2 ] = 1.0f; tex->opacity.val = 1.0f; tex->enabled = 1; sz = getU2( fp ); if ( !lwGetTHeader( fp, sz, tex ) ) { _pico_free( tex ); return NULL; } sz = bloksz - sz - 6; switch ( type ) { case ID_IMAP: ok = lwGetImageMap( fp, sz, tex ); break; case ID_PROC: ok = lwGetProcedural( fp, sz, tex ); break; case ID_GRAD: ok = lwGetGradient( fp, sz, tex ); break; default: ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR ); } if ( !ok ) { lwFreeTexture( tex ); return NULL; } set_flen( bloksz ); return tex; }
int lwValidateObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ){ unsigned int id, formsize, type; /* open the file */ if ( !fp ) { return PICO_PMV_ERROR_MEMORY; } /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { return PICO_PMV_ERROR_SIZE; } /* is this a LW object? */ if ( id != ID_FORM ) { if ( failpos ) { *failpos = 12; } return PICO_PMV_ERROR_SIZE; } if ( type != ID_LWO2 ) { if ( type == ID_LWOB ) { return lwValidateObject5( filename, fp, failID, failpos ); } else { if ( failpos ) { *failpos = 12; } return PICO_PMV_ERROR_IDENT; } } return PICO_PMV_OK; }
int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex ){ unsigned int id; unsigned short sz; int rlen, pos; pos = _pico_memstream_tell( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { return 0; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TMAP: if ( !lwGetTMap( fp, sz, &tex->tmap ) ) { return 0; } break; case ID_PROJ: tex->param.imap.projection = getU2( fp ); break; case ID_VMAP: tex->param.imap.vmap_name = getS0( fp ); break; case ID_AXIS: tex->param.imap.axis = getU2( fp ); break; case ID_IMAG: tex->param.imap.cindex = getVX( fp ); break; case ID_WRAP: tex->param.imap.wrapw_type = getU2( fp ); tex->param.imap.wraph_type = getU2( fp ); break; case ID_WRPW: tex->param.imap.wrapw.val = getF4( fp ); tex->param.imap.wrapw.eindex = getVX( fp ); break; case ID_WRPH: tex->param.imap.wraph.val = getF4( fp ); tex->param.imap.wraph.eindex = getVX( fp ); break; case ID_AAST: tex->param.imap.aas_flags = getU2( fp ); tex->param.imap.aa_strength = getF4( fp ); break; case ID_PIXB: tex->param.imap.pblend = getU2( fp ); break; case ID_STCK: tex->param.imap.stck.val = getF4( fp ); tex->param.imap.stck.eindex = getVX( fp ); break; case ID_TAMP: tex->param.imap.amplitude.val = getF4( fp ); tex->param.imap.amplitude.eindex = getVX( fp ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { return 0; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the image map? */ if ( rsz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { return 0; } } set_flen( _pico_memstream_tell( fp ) - pos ); return 1; }
int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap ){ unsigned int id; unsigned short sz; int rlen, pos, i; pos = _pico_memstream_tell( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { return 0; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_SIZE: for ( i = 0; i < 3; i++ ) tmap->size.val[ i ] = getF4( fp ); tmap->size.eindex = getVX( fp ); break; case ID_CNTR: for ( i = 0; i < 3; i++ ) tmap->center.val[ i ] = getF4( fp ); tmap->center.eindex = getVX( fp ); break; case ID_ROTA: for ( i = 0; i < 3; i++ ) tmap->rotate.val[ i ] = getF4( fp ); tmap->rotate.eindex = getVX( fp ); break; case ID_FALL: tmap->fall_type = getU2( fp ); for ( i = 0; i < 3; i++ ) tmap->falloff.val[ i ] = getF4( fp ); tmap->falloff.eindex = getVX( fp ); break; case ID_OREF: tmap->ref_object = getS0( fp ); break; case ID_CSYS: tmap->coord_sys = getU2( fp ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { return 0; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the TMAP subchunk? */ if ( tmapsz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { return 0; } } set_flen( _pico_memstream_tell( fp ) - pos ); return 1; }
int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex ){ unsigned int id; unsigned short sz; int pos, rlen; /* remember where we started */ set_flen( 0 ); pos = _pico_memstream_tell( fp ); /* ordinal string */ tex->ord = getS0( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { return 0; } /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_CHAN: tex->chan = getU4( fp ); break; case ID_OPAC: tex->opac_type = getU2( fp ); tex->opacity.val = getF4( fp ); tex->opacity.eindex = getVX( fp ); break; case ID_ENAB: tex->enabled = getU2( fp ); break; case ID_NEGA: tex->negative = getU2( fp ); break; case ID_AXIS: tex->axis = getU2( fp ); break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { return 0; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the texture header subchunk? */ if ( hsz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { return 0; } } set_flen( _pico_memstream_tell( fp ) - pos ); return 1; }
lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos ) { lwObject *object; lwLayer *layer; lwNode *node; unsigned int id, formsize, type, cksize; /* open the file */ if ( !fp ) return NULL; /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { return NULL; } /* LWOB? */ if ( id != ID_FORM || type != ID_LWOB ) { if ( failpos ) *failpos = 12; return NULL; } /* allocate an object and a default layer */ object = _pico_calloc( 1, sizeof( lwObject )); if ( !object ) goto Fail; layer = _pico_calloc( 1, sizeof( lwLayer )); if ( !layer ) goto Fail; object->layer = layer; object->nlayers = 1; /* get the first chunk header */ id = getU4( fp ); cksize = getU4( fp ); if ( 0 > get_flen() ) goto Fail; /* process chunks as they're encountered */ while ( 1 ) { cksize += cksize & 1; switch ( id ) { case ID_PNTS: if ( !lwGetPoints( fp, cksize, &layer->point )) goto Fail; break; case ID_POLS: if ( !lwGetPolygons5( fp, cksize, &layer->polygon, layer->point.offset )) goto Fail; break; case ID_SRFS: if ( !lwGetTags( fp, cksize, &object->taglist )) goto Fail; break; case ID_SURF: node = ( lwNode * ) lwGetSurface5( fp, cksize, object ); if ( !node ) goto Fail; lwListAdd( (void *) &object->surf, node ); object->nsurfs++; break; default: _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR ); break; } /* end of the file? */ if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break; /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); cksize = getU4( fp ); if ( 8 != get_flen() ) goto Fail; } lwGetBoundingBox( &layer->point, layer->bbox ); lwGetPolyNormals( &layer->point, &layer->polygon ); if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail; if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist, &object->surf, &object->nsurfs )) goto Fail; lwGetVertNormals( &layer->point, &layer->polygon ); return object; Fail: if ( failID ) *failID = id; if ( fp ) { if ( failpos ) *failpos = _pico_memstream_tell( fp ); } lwFreeObject( object ); return NULL; }
lwClip *lwGetClip( FILE *fp, int cksize ) { lwClip *clip; lwPlugin *filt; unsigned int id; unsigned short sz; int pos, rlen; /* allocate the Clip structure */ clip = calloc( 1, sizeof( lwClip )); if ( !clip ) goto Fail; clip->contrast.val = 1.0f; clip->brightness.val = 1.0f; clip->saturation.val = 1.0f; clip->gamma.val = 1.0f; /* remember where we started */ set_flen( 0 ); pos = ftell( fp ); /* index */ clip->index = getI4( fp ); /* first subchunk header */ clip->type = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) goto Fail; sz += sz & 1; set_flen( 0 ); switch ( clip->type ) { case ID_STIL: clip->source.still.name = getS0( fp ); break; case ID_ISEQ: clip->source.seq.digits = getU1( fp ); clip->source.seq.flags = getU1( fp ); clip->source.seq.offset = getI2( fp ); getU2( fp ); /* Legacy Cruft: Nothing to see here */ clip->source.seq.start = getI2( fp ); clip->source.seq.end = getI2( fp ); clip->source.seq.prefix = getS0( fp ); clip->source.seq.suffix = getS0( fp ); break; case ID_ANIM: clip->source.anim.name = getS0( fp ); clip->source.anim.server = getS0( fp ); rlen = get_flen(); clip->source.anim.data = getbytes( fp, sz - rlen ); break; case ID_XREF: clip->source.xref.index = getI4( fp ); clip->source.xref.string = getS0( fp ); break; case ID_STCC: clip->source.cycle.lo = getI2( fp ); clip->source.cycle.hi = getI2( fp ); clip->source.cycle.name = getS0( fp ); break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) goto Fail; /* skip unread parts of the current subchunk */ if ( rlen < sz ) fseek( fp, sz - rlen, SEEK_CUR ); /* end of the CLIP chunk? */ rlen = ftell( fp ) - pos; if ( cksize < rlen ) goto Fail; if ( cksize == rlen ) return clip; /* process subchunks as they're encountered */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) goto Fail; while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TIME: clip->start_time = getF4( fp ); clip->duration = getF4( fp ); clip->frame_rate = getF4( fp ); break; case ID_CONT: clip->contrast.val = getF4( fp ); clip->contrast.eindex = getVX( fp ); break; case ID_BRIT: clip->brightness.val = getF4( fp ); clip->brightness.eindex = getVX( fp ); break; case ID_SATR: clip->saturation.val = getF4( fp ); clip->saturation.eindex = getVX( fp ); break; case ID_HUE: clip->hue.val = getF4( fp ); clip->hue.eindex = getVX( fp ); break; case ID_GAMM: clip->gamma.val = getF4( fp ); clip->gamma.eindex = getVX( fp ); break; case ID_NEGA: clip->negative = getU2( fp ); break; case ID_IFLT: case ID_PFLT: filt = calloc( 1, sizeof( lwPlugin )); if ( !filt ) goto Fail; filt->name = getS0( fp ); filt->flags = getU2( fp ); rlen = get_flen(); filt->data = getbytes( fp, sz - rlen ); if ( id == ID_IFLT ) { lwListAdd( &clip->ifilter, filt ); clip->nifilters++; } else { lwListAdd( &clip->pfilter, filt ); clip->npfilters++; } break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) goto Fail; /* skip unread parts of the current subchunk */ if ( rlen < sz ) fseek( fp, sz - rlen, SEEK_CUR ); /* end of the CLIP chunk? */ rlen = ftell( fp ) - pos; if ( cksize < rlen ) goto Fail; if ( cksize == rlen ) break; /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) goto Fail; } return clip; Fail: lwFreeClip( clip ); return NULL; }
lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz ){ lwPlugin *shdr; unsigned int id; unsigned short sz; int hsz, rlen, pos; shdr = _pico_calloc( 1, sizeof( lwPlugin ) ); if ( !shdr ) { return NULL; } pos = _pico_memstream_tell( fp ); set_flen( 0 ); hsz = getU2( fp ); shdr->ord = getS0( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } while ( hsz > 0 ) { sz += sz & 1; hsz -= sz; if ( id == ID_ENAB ) { shdr->flags = getU2( fp ); break; } else { _pico_memstream_seek( fp, sz, PICO_SEEK_CUR ); id = getU4( fp ); sz = getU2( fp ); } } id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_FUNC: shdr->name = getS0( fp ); rlen = get_flen(); shdr->data = getbytes( fp, sz - rlen ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { goto Fail; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the shader block? */ if ( bloksz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { goto Fail; } } set_flen( _pico_memstream_tell( fp ) - pos ); return shdr; Fail: lwFreePlugin( shdr ); return NULL; }
lwObject *lwGetObject( char *filename, unsigned int *failID, int *failpos ) { FILE *fp = NULL; lwObject *object; lwLayer *layer; lwNode *node; unsigned int id, formsize, type, cksize; int i, rlen; /* open the file */ fp = fopen( filename, "rb" ); if ( !fp ) return NULL; /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { fclose( fp ); return NULL; } /* is this a LW object? */ if ( id != ID_FORM ) { fclose( fp ); if ( failpos ) *failpos = 12; return NULL; } if ( type != ID_LWO2 ) { fclose( fp ); if ( type == ID_LWOB ) return lwGetObject5( filename, failID, failpos ); else { if ( failpos ) *failpos = 12; return NULL; } } /* allocate an object and a default layer */ object = calloc( 1, sizeof( lwObject )); if ( !object ) goto Fail; layer = calloc( 1, sizeof( lwLayer )); if ( !layer ) goto Fail; object->layer = layer; /* get the first chunk header */ id = getU4( fp ); cksize = getU4( fp ); if ( 0 > get_flen() ) goto Fail; /* process chunks as they're encountered */ while ( 1 ) { cksize += cksize & 1; switch ( id ) { case ID_LAYR: if ( object->nlayers > 0 ) { layer = calloc( 1, sizeof( lwLayer )); if ( !layer ) goto Fail; lwListAdd( &object->layer, layer ); } object->nlayers++; set_flen( 0 ); layer->index = getU2( fp ); layer->flags = getU2( fp ); layer->pivot[ 0 ] = getF4( fp ); layer->pivot[ 1 ] = getF4( fp ); layer->pivot[ 2 ] = getF4( fp ); layer->name = getS0( fp ); rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) goto Fail; if ( rlen <= cksize - 2 ) layer->parent = getU2( fp ); if ( rlen < cksize ) fseek( fp, cksize - rlen, SEEK_CUR ); break; case ID_PNTS: if ( !lwGetPoints( fp, cksize, &layer->point )) goto Fail; break; case ID_POLS: if ( !lwGetPolygons( fp, cksize, &layer->polygon, layer->point.offset )) goto Fail; break; case ID_VMAP: case ID_VMAD: node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset, layer->polygon.offset, id == ID_VMAD ); if ( !node ) goto Fail; lwListAdd( &layer->vmap, node ); layer->nvmaps++; break; case ID_PTAG: if ( !lwGetPolygonTags( fp, cksize, &object->taglist, &layer->polygon )) goto Fail; break; case ID_BBOX: set_flen( 0 ); for ( i = 0; i < 6; i++ ) layer->bbox[ i ] = getF4( fp ); rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) goto Fail; if ( rlen < cksize ) fseek( fp, cksize - rlen, SEEK_CUR ); break; case ID_TAGS: if ( !lwGetTags( fp, cksize, &object->taglist )) goto Fail; break; case ID_ENVL: node = ( lwNode * ) lwGetEnvelope( fp, cksize ); if ( !node ) goto Fail; lwListAdd( &object->env, node ); object->nenvs++; break; case ID_CLIP: node = ( lwNode * ) lwGetClip( fp, cksize ); if ( !node ) goto Fail; lwListAdd( &object->clip, node ); object->nclips++; break; case ID_SURF: node = ( lwNode * ) lwGetSurface( fp, cksize ); if ( !node ) goto Fail; lwListAdd( &object->surf, node ); object->nsurfs++; break; case ID_DESC: case ID_TEXT: case ID_ICON: default: fseek( fp, cksize, SEEK_CUR ); break; } /* end of the file? */ if ( formsize <= ftell( fp ) - 8 ) break; /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); cksize = getU4( fp ); if ( 8 != get_flen() ) goto Fail; } fclose( fp ); fp = NULL; if ( object->nlayers == 0 ) object->nlayers = 1; layer = object->layer; while ( layer ) { lwGetBoundingBox( &layer->point, layer->bbox ); lwGetPolyNormals( &layer->point, &layer->polygon ); if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail; if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist, &object->surf, &object->nsurfs )) goto Fail; lwGetVertNormals( &layer->point, &layer->polygon ); if ( !lwGetPointVMaps( &layer->point, layer->vmap )) goto Fail; if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap )) goto Fail; layer = layer->next; } return object; Fail: if ( failID ) *failID = id; if ( fp ) { if ( failpos ) *failpos = ftell( fp ); fclose( fp ); } lwFreeObject( object ); return NULL; }
lwEnvelope *lwGetEnvelope( FILE *fp, int cksize ) { lwEnvelope *env; lwKey *key; lwPlugin *plug; unsigned int id; unsigned short sz; float f[ 4 ]; int i, nparams, pos, rlen; /* allocate the Envelope structure */ env = calloc( 1, sizeof( lwEnvelope )); if ( !env ) goto Fail; /* remember where we started */ set_flen( 0 ); pos = ftell( fp ); /* index */ env->index = getVX( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) goto Fail; /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TYPE: env->type = getU2( fp ); break; case ID_NAME: env->name = getS0( fp ); break; case ID_PRE: env->behavior[ 0 ] = getU2( fp ); break; case ID_POST: env->behavior[ 1 ] = getU2( fp ); break; case ID_KEY: key = calloc( 1, sizeof( lwKey )); if ( !key ) goto Fail; key->time = getF4( fp ); key->value = getF4( fp ); lwListInsert( &env->key, key, compare_keys ); env->nkeys++; break; case ID_SPAN: if ( !key ) goto Fail; key->shape = getU4( fp ); nparams = ( sz - 4 ) / 4; if ( nparams > 4 ) nparams = 4; for ( i = 0; i < nparams; i++ ) f[ i ] = getF4( fp ); switch ( key->shape ) { case ID_TCB: key->tension = f[ 0 ]; key->continuity = f[ 1 ]; key->bias = f[ 2 ]; break; case ID_BEZI: case ID_HERM: case ID_BEZ2: for ( i = 0; i < nparams; i++ ) key->param[ i ] = f[ i ]; break; } break; case ID_CHAN: plug = calloc( 1, sizeof( lwPlugin )); if ( !plug ) goto Fail; plug->name = getS0( fp ); plug->flags = getU2( fp ); plug->data = getbytes( fp, sz - get_flen() ); lwListAdd( &env->cfilter, plug ); env->ncfilters++; break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) goto Fail; /* skip unread parts of the current subchunk */ if ( rlen < sz ) fseek( fp, sz - rlen, SEEK_CUR ); /* end of the ENVL chunk? */ rlen = ftell( fp ) - pos; if ( cksize < rlen ) goto Fail; if ( cksize == rlen ) break; /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) goto Fail; } return env; Fail: lwFreeEnvelope( env ); return NULL; }
int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset ){ lwPolygon *pp; lwPolVert *pv; unsigned char *buf, *bp; int i, j, flags, nv, nverts, npols; unsigned int type; if ( cksize == 0 ) { return 1; } /* read the whole chunk */ set_flen( 0 ); type = getU4( fp ); buf = getbytes( fp, cksize - 4 ); if ( cksize != get_flen() ) { goto Fail; } /* count the polygons and vertices */ nverts = 0; npols = 0; bp = buf; while ( bp < buf + cksize - 4 ) { nv = sgetU2( &bp ); nv &= 0x03FF; nverts += nv; npols++; for ( i = 0; i < nv; i++ ) j = sgetVX( &bp ); } if ( !lwAllocPolygons( plist, npols, nverts ) ) { goto Fail; } /* fill in the new polygons */ bp = buf; pp = plist->pol + plist->offset; pv = plist->pol[ 0 ].v + plist->voffset; for ( i = 0; i < npols; i++ ) { nv = sgetU2( &bp ); flags = nv & 0xFC00; nv &= 0x03FF; pp->nverts = nv; pp->flags = flags; pp->type = type; if ( !pp->v ) { pp->v = pv; } for ( j = 0; j < nv; j++ ) pp->v[ j ].index = sgetVX( &bp ) + ptoffset; pp++; pv += nv; } _pico_free( buf ); return 1; Fail: if ( buf ) { _pico_free( buf ); } lwFreePolygons( plist ); return 0; }
Flex *flexReadBegin( char *filename, unsigned int *failID, int *failpos ) { FILE *fp = NULL; Flex *flex; Frame *frame = NULL; Layer *layer = NULL; unsigned int id, formsize, type, cksize; int rlen, nframes = 0, nlayers = 0; /* open the file */ fp = fopen( filename, "rb" ); if ( !fp ) return NULL; /* read the first 12 bytes */ set_flen( 0 ); id = getU4( fp ); formsize = getU4( fp ); type = getU4( fp ); if ( 12 != get_flen() ) { fclose( fp ); return NULL; } /* is this a flex image? */ if ( id != ID_FORM ) { fclose( fp ); if ( failpos ) *failpos = 12; return NULL; } if ( type != ID_FPBM ) { fclose( fp ); if ( failpos ) *failpos = 12; return NULL; } /* allocate a Flex */ flex = calloc( 1, sizeof( Flex )); if ( !flex ) goto Fail; /* get the first chunk header */ id = getU4( fp ); cksize = getU4( fp ); if ( 0 > get_flen() ) goto Fail; /* process chunks as they're encountered */ while ( 1 ) { set_flen( 0 ); switch ( id ) { case ID_FPHD: if(cksize==28) // Older file version { flex->hdr.width = getI2( fp ); flex->hdr.height = getI2( fp ); } else // cksize==32 { flex->hdr.width = getI4( fp ); flex->hdr.height = getI4( fp ); } flex->hdr.numLayers = getI2( fp ); flex->hdr.numFrames = getI2( fp ); flex->hdr.numBuffers = getI2( fp ); flex->hdr.flags = getI2( fp ); flex->hdr.srcLayerDepth = getI2( fp ); skipbytes( fp, 2 ); flex->hdr.pixelAspect = getF4( fp ); flex->hdr.pixelWidth = getF4( fp ); flex->hdr.framesPerSecond = getF4( fp ); frame = calloc( flex->hdr.numFrames, sizeof( Frame )); if ( !frame ) goto Fail; flex->frame = frame; break; case ID_FLEX: if ( !frame ) goto Fail; if ( nframes >= flex->hdr.numFrames ) goto Fail; nlayers = getI2( fp ); layer = calloc( nlayers, sizeof( Layer )); if ( !layer ) goto Fail; frame[ nframes ].layer = layer; frame[ nframes ].hdr.numLayers = nlayers; nlayers = 0; ++nframes; break; case ID_LYHD: if ( !layer ) goto Fail; if ( nlayers >= frame[ nframes - 1 ].hdr.numLayers ) goto Fail; layer[ nlayers ].w = flex->hdr.width; layer[ nlayers ].h = flex->hdr.height; layer[ nlayers ].hdr.flags = getI2( fp ); layer[ nlayers ].hdr.layerType = getI2( fp ); layer[ nlayers ].hdr.layerDepth = getI2( fp ); layer[ nlayers ].hdr.compression = getI2( fp ); layer[ nlayers ].hdr.blackPoint = getF4( fp ); layer[ nlayers ].hdr.whitePoint = getF4( fp ); layer[ nlayers ].hdr.gamma = getF4( fp ); break; case ID_LAYR: if ( !layer ) goto Fail; layer[ nlayers ].offset = ftell( fp ); layer[ nlayers ].size = cksize; ++nlayers; break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > cksize ) goto Fail; /* skip unread parts of the current subchunk */ cksize += cksize & 1; if ( rlen < cksize ) fseek( fp, cksize - rlen, SEEK_CUR ); /* end of the file? */ if ( formsize <= ftell( fp ) - 8 ) break; /* get the next chunk header */ set_flen( 0 ); id = getU4( fp ); cksize = getU4( fp ); if ( 8 != get_flen() ) goto Fail; } flex->fp = fp; return flex; Fail: if ( failID ) *failID = id; if ( fp ) { if ( failpos ) *failpos = ftell( fp ); fclose( fp ); } flexFree( flex ); return NULL; }
int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex ){ unsigned int id; unsigned short sz; int rlen, pos; pos = _pico_memstream_tell( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { return 0; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TMAP: if ( !lwGetTMap( fp, sz, &tex->tmap ) ) { return 0; } break; case ID_AXIS: tex->param.proc.axis = getU2( fp ); break; case ID_VALU: tex->param.proc.value[ 0 ] = getF4( fp ); if ( sz >= 8 ) { tex->param.proc.value[ 1 ] = getF4( fp ); } if ( sz >= 12 ) { tex->param.proc.value[ 2 ] = getF4( fp ); } break; case ID_FUNC: tex->param.proc.name = getS0( fp ); rlen = get_flen(); tex->param.proc.data = getbytes( fp, sz - rlen ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { return 0; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the procedural block? */ if ( rsz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { return 0; } } set_flen( _pico_memstream_tell( fp ) - pos ); return 1; }
int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex ){ unsigned int id; unsigned short sz; int rlen, pos, i, j, nkeys; pos = _pico_memstream_tell( fp ); id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { return 0; } while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_TMAP: if ( !lwGetTMap( fp, sz, &tex->tmap ) ) { return 0; } break; case ID_PNAM: tex->param.grad.paramname = getS0( fp ); break; case ID_INAM: tex->param.grad.itemname = getS0( fp ); break; case ID_GRST: tex->param.grad.start = getF4( fp ); break; case ID_GREN: tex->param.grad.end = getF4( fp ); break; case ID_GRPT: tex->param.grad.repeat = getU2( fp ); break; case ID_FKEY: nkeys = sz / sizeof( lwGradKey ); tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ) ); if ( !tex->param.grad.key ) { return 0; } for ( i = 0; i < nkeys; i++ ) { tex->param.grad.key[ i ].value = getF4( fp ); for ( j = 0; j < 4; j++ ) tex->param.grad.key[ i ].rgba[ j ] = getF4( fp ); } break; case ID_IKEY: nkeys = sz / 2; tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ) ); if ( !tex->param.grad.ikey ) { return 0; } for ( i = 0; i < nkeys; i++ ) tex->param.grad.ikey[ i ] = getU2( fp ); break; default: break; } /* error while reading the current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { return 0; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the gradient? */ if ( rsz <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { return 0; } } set_flen( _pico_memstream_tell( fp ) - pos ); return 1; }
lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj ) { lwSurface *surf; lwTexture *tex; lwPlugin *shdr; char *s; float v[ 3 ]; unsigned int id, flags; unsigned short sz; int pos, rlen, i; tex = NULL; shdr = NULL; /* allocate the Surface structure */ surf = _pico_calloc( 1, sizeof( lwSurface )); if ( !surf ) goto Fail; /* non-zero defaults */ surf->color.rgb[ 0 ] = 0.78431f; surf->color.rgb[ 1 ] = 0.78431f; surf->color.rgb[ 2 ] = 0.78431f; surf->diffuse.val = 1.0f; surf->glossiness.val = 0.4f; surf->bump.val = 1.0f; surf->eta.val = 1.0f; surf->sideflags = 1; /* remember where we started */ set_flen( 0 ); pos = _pico_memstream_tell( fp ); /* name */ surf->name = getS0( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) goto Fail; /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_COLR: surf->color.rgb[ 0 ] = getU1( fp ) / 255.0f; surf->color.rgb[ 1 ] = getU1( fp ) / 255.0f; surf->color.rgb[ 2 ] = getU1( fp ) / 255.0f; break; case ID_FLAG: flags = getU2( fp ); if ( flags & 4 ) surf->smooth = 1.56207f; if ( flags & 8 ) surf->color_hilite.val = 1.0f; if ( flags & 16 ) surf->color_filter.val = 1.0f; if ( flags & 128 ) surf->dif_sharp.val = 0.5f; if ( flags & 256 ) surf->sideflags = 3; if ( flags & 512 ) surf->add_trans.val = 1.0f; break; case ID_LUMI: surf->luminosity.val = getI2( fp ) / 256.0f; break; case ID_VLUM: surf->luminosity.val = getF4( fp ); break; case ID_DIFF: surf->diffuse.val = getI2( fp ) / 256.0f; break; case ID_VDIF: surf->diffuse.val = getF4( fp ); break; case ID_SPEC: surf->specularity.val = getI2( fp ) / 256.0f; break; case ID_VSPC: surf->specularity.val = getF4( fp ); break; case ID_GLOS: surf->glossiness.val = ( float ) log( getU2( fp )) / 20.7944f; break; case ID_SMAN: surf->smooth = getF4( fp ); break; case ID_REFL: surf->reflection.val.val = getI2( fp ) / 256.0f; break; case ID_RFLT: surf->reflection.options = getU2( fp ); break; case ID_RIMG: s = getS0( fp ); surf->reflection.cindex = add_clip( s, &obj->clip, &obj->nclips ); surf->reflection.options = 3; break; case ID_RSAN: surf->reflection.seam_angle = getF4( fp ); break; case ID_TRAN: surf->transparency.val.val = getI2( fp ) / 256.0f; break; case ID_RIND: surf->eta.val = getF4( fp ); break; case ID_BTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->bump.tex, tex ); break; case ID_CTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->color.tex, tex ); break; case ID_DTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->diffuse.tex, tex ); break; case ID_LTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->luminosity.tex, tex ); break; case ID_RTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->reflection.val.tex, tex ); break; case ID_STEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->specularity.tex, tex ); break; case ID_TTEX: s = getbytes( fp, sz ); tex = get_texture( s ); lwListAdd( (void *) &surf->transparency.val.tex, tex ); break; case ID_TFLG: flags = getU2( fp ); i = 0; // greebo: initialise to fix compiler warnings if ( flags & 1 ) i = 0; if ( flags & 2 ) i = 1; if ( flags & 4 ) i = 2; tex->axis = i; if ( tex->type == ID_IMAP ) tex->param.imap.axis = i; else tex->param.proc.axis = i; if ( flags & 8 ) tex->tmap.coord_sys = 1; if ( flags & 16 ) tex->negative = 1; if ( flags & 32 ) tex->param.imap.pblend = 1; if ( flags & 64 ) { tex->param.imap.aa_strength = 1.0f; tex->param.imap.aas_flags = 1; } break; case ID_TSIZ: for ( i = 0; i < 3; i++ ) tex->tmap.size.val[ i ] = getF4( fp ); break; case ID_TCTR: for ( i = 0; i < 3; i++ ) tex->tmap.center.val[ i ] = getF4( fp ); break; case ID_TFAL: for ( i = 0; i < 3; i++ ) tex->tmap.falloff.val[ i ] = getF4( fp ); break; case ID_TVEL: for ( i = 0; i < 3; i++ ) v[ i ] = getF4( fp ); tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v, &obj->env, &obj->nenvs ); break; case ID_TCLR: if ( tex->type == ID_PROC ) for ( i = 0; i < 3; i++ ) tex->param.proc.value[ i ] = getU1( fp ) / 255.0f; break; case ID_TVAL: tex->param.proc.value[ 0 ] = getI2( fp ) / 256.0f; break; case ID_TAMP: if ( tex->type == ID_IMAP ) tex->param.imap.amplitude.val = getF4( fp ); break; case ID_TIMG: s = getS0( fp ); tex->param.imap.cindex = add_clip( s, &obj->clip, &obj->nclips ); break; case ID_TAAS: tex->param.imap.aa_strength = getF4( fp ); tex->param.imap.aas_flags = 1; break; case ID_TREF: tex->tmap.ref_object = getbytes( fp, sz ); break; case ID_TOPC: tex->opacity.val = getF4( fp ); break; case ID_TFP0: if ( tex->type == ID_IMAP ) tex->param.imap.wrapw.val = getF4( fp ); break; case ID_TFP1: if ( tex->type == ID_IMAP ) tex->param.imap.wraph.val = getF4( fp ); break; case ID_SHDR: shdr = _pico_calloc( 1, sizeof( lwPlugin )); if ( !shdr ) goto Fail; shdr->name = getbytes( fp, sz ); lwListAdd( (void *) &surf->shader, shdr ); surf->nshaders++; break; case ID_SDAT: shdr->data = getbytes( fp, sz ); break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) goto Fail; /* skip unread parts of the current subchunk */ if ( rlen < sz ) _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); /* end of the SURF chunk? */ if ( cksize <= _pico_memstream_tell( fp ) - pos ) break; /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) goto Fail; } return surf; Fail: if ( surf ) lwFreeSurface( surf ); return NULL; }
lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize ){ lwSurface *surf; lwTexture *tex; lwPlugin *shdr; unsigned int id, type; unsigned short sz; int pos, rlen; /* allocate the Surface structure */ surf = _pico_calloc( 1, sizeof( lwSurface ) ); if ( !surf ) { goto Fail; } /* non-zero defaults */ surf->color.rgb[ 0 ] = 0.78431f; surf->color.rgb[ 1 ] = 0.78431f; surf->color.rgb[ 2 ] = 0.78431f; surf->diffuse.val = 1.0f; surf->glossiness.val = 0.4f; surf->bump.val = 1.0f; surf->eta.val = 1.0f; surf->sideflags = 1; /* remember where we started */ set_flen( 0 ); pos = _pico_memstream_tell( fp ); /* names */ surf->name = getS0( fp ); surf->srcname = getS0( fp ); /* first subchunk header */ id = getU4( fp ); sz = getU2( fp ); if ( 0 > get_flen() ) { goto Fail; } /* process subchunks as they're encountered */ while ( 1 ) { sz += sz & 1; set_flen( 0 ); switch ( id ) { case ID_COLR: surf->color.rgb[ 0 ] = getF4( fp ); surf->color.rgb[ 1 ] = getF4( fp ); surf->color.rgb[ 2 ] = getF4( fp ); surf->color.eindex = getVX( fp ); break; case ID_LUMI: surf->luminosity.val = getF4( fp ); surf->luminosity.eindex = getVX( fp ); break; case ID_DIFF: surf->diffuse.val = getF4( fp ); surf->diffuse.eindex = getVX( fp ); break; case ID_SPEC: surf->specularity.val = getF4( fp ); surf->specularity.eindex = getVX( fp ); break; case ID_GLOS: surf->glossiness.val = getF4( fp ); surf->glossiness.eindex = getVX( fp ); break; case ID_REFL: surf->reflection.val.val = getF4( fp ); surf->reflection.val.eindex = getVX( fp ); break; case ID_RFOP: surf->reflection.options = getU2( fp ); break; case ID_RIMG: surf->reflection.cindex = getVX( fp ); break; case ID_RSAN: surf->reflection.seam_angle = getF4( fp ); break; case ID_TRAN: surf->transparency.val.val = getF4( fp ); surf->transparency.val.eindex = getVX( fp ); break; case ID_TROP: surf->transparency.options = getU2( fp ); break; case ID_TIMG: surf->transparency.cindex = getVX( fp ); break; case ID_RIND: surf->eta.val = getF4( fp ); surf->eta.eindex = getVX( fp ); break; case ID_TRNL: surf->translucency.val = getF4( fp ); surf->translucency.eindex = getVX( fp ); break; case ID_BUMP: surf->bump.val = getF4( fp ); surf->bump.eindex = getVX( fp ); break; case ID_SMAN: surf->smooth = getF4( fp ); break; case ID_SIDE: surf->sideflags = getU2( fp ); break; case ID_CLRH: surf->color_hilite.val = getF4( fp ); surf->color_hilite.eindex = getVX( fp ); break; case ID_CLRF: surf->color_filter.val = getF4( fp ); surf->color_filter.eindex = getVX( fp ); break; case ID_ADTR: surf->add_trans.val = getF4( fp ); surf->add_trans.eindex = getVX( fp ); break; case ID_SHRP: surf->dif_sharp.val = getF4( fp ); surf->dif_sharp.eindex = getVX( fp ); break; case ID_GVAL: surf->glow.val = getF4( fp ); surf->glow.eindex = getVX( fp ); break; case ID_LINE: surf->line.enabled = 1; if ( sz >= 2 ) { surf->line.flags = getU2( fp ); } if ( sz >= 6 ) { surf->line.size.val = getF4( fp ); } if ( sz >= 8 ) { surf->line.size.eindex = getVX( fp ); } break; case ID_ALPH: surf->alpha_mode = getU2( fp ); surf->alpha = getF4( fp ); break; case ID_AVAL: surf->alpha = getF4( fp ); break; case ID_BLOK: type = getU4( fp ); switch ( type ) { case ID_IMAP: case ID_PROC: case ID_GRAD: tex = lwGetTexture( fp, sz - 4, type ); if ( !tex ) { goto Fail; } if ( !add_texture( surf, tex ) ) { lwFreeTexture( tex ); } set_flen( 4 + get_flen() ); break; case ID_SHDR: shdr = lwGetShader( fp, sz - 4 ); if ( !shdr ) { goto Fail; } lwListInsert( (void **) &surf->shader, shdr, (void *) compare_shaders ); ++surf->nshaders; set_flen( 4 + get_flen() ); break; } break; default: break; } /* error while reading current subchunk? */ rlen = get_flen(); if ( rlen < 0 || rlen > sz ) { goto Fail; } /* skip unread parts of the current subchunk */ if ( rlen < sz ) { _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR ); } /* end of the SURF chunk? */ if ( cksize <= _pico_memstream_tell( fp ) - pos ) { break; } /* get the next subchunk header */ set_flen( 0 ); id = getU4( fp ); sz = getU2( fp ); if ( 6 != get_flen() ) { goto Fail; } } return surf; Fail: if ( surf ) { lwFreeSurface( surf ); } return NULL; }
int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset ) { lwPolygon *pp; lwPolVert *pv; unsigned char *buf, *bp; int i, j, nv, nverts, npols; if ( cksize == 0 ) return 1; /* read the whole chunk */ set_flen( 0 ); buf = getbytes( fp, cksize ); if ( !buf ) goto Fail; /* count the polygons and vertices */ nverts = 0; npols = 0; bp = buf; while ( bp < buf + cksize ) { nv = sgetU2( &bp ); nverts += nv; npols++; bp += 2 * nv; i = sgetI2( &bp ); if ( i < 0 ) bp += 2; /* detail polygons */ } if ( !lwAllocPolygons( plist, npols, nverts )) goto Fail; /* fill in the new polygons */ bp = buf; pp = plist->pol + plist->offset; pv = plist->pol[ 0 ].v + plist->voffset; for ( i = 0; i < npols; i++ ) { nv = sgetU2( &bp ); pp->nverts = nv; pp->type = ID_FACE; if ( !pp->v ) pp->v = pv; for ( j = 0; j < nv; j++ ) pv[ j ].index = sgetU2( &bp ) + ptoffset; j = sgetI2( &bp ); if ( j < 0 ) { j = -j; bp += 2; } j -= 1; pp->surf = ( lwSurface * ) j; pp++; pv += nv; } _pico_free( buf ); return 1; Fail: if ( buf ) _pico_free( buf ); lwFreePolygons( plist ); return 0; }