Ejemplo n.º 1
0
bool JavaClass::parseJavaClass(char* data)
{
	int idx = 0;
	
	magic = getU4(&data[idx]); // magic
	idx += 4;
	
	if(magic != 0xCAFEBABE)
		return false;
	
	minor_version = getU2(&data[idx]); // minor_version
	idx += 2;
	major_version = getU2(&data[idx]); // major_version
	idx += 2;
	constant_pool_count = getU2(&data[idx]); // constant_pool_count
	idx += 2;
	
	// Cp info
	if(constant_pool_count > 0)
		parseCpInfo(data, idx);	
	
	access_flags = getU2(&data[idx]); // access_flags
	idx += 2;
	this_class = getU2(&data[idx]); // this_class
	idx += 2;
	super_class = getU2(&data[idx]); // super_class
	idx += 2;
	interfaces_count = getU2(&data[idx]); // interfaces_count
	idx += 2;
	
	// Interfaces
	if(interfaces_count > 0)
		parseInterfaces(data, idx);
	
	fields_count = getU2(&data[idx]); // fields_count
	idx += 2;
	
	// Field info
	if(fields_count > 0)
		parseFieldInfo(data, idx);
	
	methods_count = getU2(&data[idx]); // methods_count
	idx += 2;
	
	// Methods info
	if(methods_count > 0)
		parseMethodInfo(data, idx);
		
	attributes_count = getU2(&data[idx]); // attributes_count
	idx += 2;
	
	// Attributes info
	if(attributes_count > 0)
		parseAttributeInfo(data, idx);
		
	return true;
}
Ejemplo n.º 2
0
void JavaClass::parseMethodCodeAttribute(int nMethodIndex, Code_attribute* pCode_attr)
{
	if(methods == NULL || nMethodIndex > methods_count) return;
	char *pMi, *bc;
	pMi = bc = (char*)methods[nMethodIndex].pMethodInfoBase;
	bc += 6;
	int nAttributes = getU2(bc);
	bc += 2;
	
	if(nAttributes > 0)
	{
		//skip attributes
		for(int a = 0; a < nAttributes; a++)
		{
			unsigned short name_index = getU2(bc);
			bc += 2;		
			std::string strAttributeName;
			getStringFromConstPool(name_index, strAttributeName);
			
			//std::cout << "Attribute name: " << strAttributeName << std::endl;

			if(strAttributeName == "Code")
			{
				char* ca = bc;
				pCode_attr->attribute_name_index = name_index; //already scanned;
				pCode_attr->attribute_length = getU4(ca); ca += 4;
				pCode_attr->max_stack = getU2(ca); ca += 2;
				pCode_attr->max_locals = getU2(ca); ca += 2;
				pCode_attr->code_length = getU4(ca); ca += 4;
				if(pCode_attr->code_length > 0)
				{
					pCode_attr->code = new unsigned char[pCode_attr->code_length];
					memcpy(pCode_attr->code, ca, pCode_attr->code_length);
				}
				else
				{
					// may be native code ??
					pCode_attr->code = NULL;
				}
				ca += pCode_attr->code_length;
				pCode_attr->exception_table_length = getU2(ca); ca += 2;

				if(pCode_attr->exception_table_length > 0)
				{
					pCode_attr->exception_table = new Exception_table[pCode_attr->exception_table_length];
					for(int ext = 0; ext < pCode_attr->exception_table_length; ext++)
					{
						pCode_attr->exception_table[ext].start_pc = getU2(ca); ca += 2;
						pCode_attr->exception_table[ext].end_pc = getU2(ca); ca += 2;
						pCode_attr->exception_table[ext].handler_pc = getU2(ca); ca += 2;
						pCode_attr->exception_table[ext].catch_type = getU2(ca); ca += 2;
					}
				}				
			}

			unsigned int len = getU4(bc); bc += 4;
			bc += len;
		}
	}
}
Ejemplo n.º 3
0
void JavaClass::parseFieldInfo(char* data, int& idx)
{
	fields = new field_info_ex[fields_count];

	if(fields == NULL) return;
	
	for(int i = 0; i < fields_count; i++)
	{
		fields[i].pFieldInfoBase = (field_info*)(&data[idx]);
		
		fields[i].access_flags = getU2(&data[idx]);
		idx += 2;
		fields[i].name_index = getU2(&data[idx]);
		idx += 2;
		fields[i].descriptor_index = getU2(&data[idx]);
		idx += 2;
		fields[i].attributes_count = getU2(&data[idx]);
		idx += 2;
		
		//std::cout << "Field " << i << " has total " << fields[i].attributes_count << " attributes" << std::endl;
		if(fields[i].attributes_count > 0)
		{
			fields[i].attributes = new attribute_info[fields[i].attributes_count];

			for(int a = 0; a < fields[i].attributes_count; a++)
			{					
				unsigned short attribute_name_index = getU2(&data[idx]);
				idx += 2;
				
				std::string attributeType;
				getStringFromConstPool(attribute_name_index, attributeType);
				
				if(attributeType == "ConstantValue")
				{
					char* ca = &data[idx];
					fields[i].attributes[a].attribute_name_index = attribute_name_index;
					fields[i].attributes[a].attribute_length = getU4(ca);
					ca += 4;
					if(fields[i].attributes[a].attribute_length > 0)
					{
						fields[i].attributes[a].info = new unsigned char[fields[i].attributes[a].attribute_length];
						memcpy(fields[i].attributes[a].info, ca, fields[i].attributes[a].attribute_length);
						ca += fields[i].attributes[a].attribute_length;
					}
				}
				
				unsigned int len = getU4(&data[idx]);
				idx += 4;
				idx += len;
			}
		}
	}
}
Ejemplo n.º 4
0
int JavaClass::getConstantPoolSize(char* data, int& idx)
{
	cp_info* cp = (cp_info*)(&data[idx]);

	switch(cp->tag)
	{
		case CONSTANT_Class:
			return 3;
		case CONSTANT_Fieldref:
			return 5;
		case CONSTANT_Methodref:
			return 5;
		case CONSTANT_InterfaceMethodref:
			return 5;
		case CONSTANT_String:
			return 3;
		case CONSTANT_Integer:
			return 5;
		case CONSTANT_Float:
			return 5;
		case CONSTANT_Long:
			return 9;
		case CONSTANT_Double:
			return 9;
		case CONSTANT_NameAndType:
			return 5;
		case CONSTANT_Utf8:
			return (3 + getU2(&data[idx+1]));
	}
	
	return 0;
}
Ejemplo n.º 5
0
void JavaClass::parseInterfaces(char* data, int& idx)
{	
	interfaces = new unsigned short[interfaces_count];
	
	for(int i = 0; i < interfaces_count; i++)
	{
		interfaces[i] = getU2(&data[idx]);
		idx += 2;
		std::cout << "Interface at " << (int)interfaces[i] << std::endl;
	}
}
Ejemplo n.º 6
0
void JavaClass::parseMethodInfo(char* data, int& idx)
{
	methods = new method_info_ex[methods_count];

	if(methods == NULL) return;
	
	for(int i = 0; i < methods_count; i++)
	{
		//methods[i] = new method_info_ex;
		methods[i].pMethodInfoBase = (method_info*)(&data[idx]);
		methods[i].access_flags = getU2(&data[idx]);     // access_flags
		idx += 2;
		methods[i].name_index = getU2(&data[idx]);       // name_index
		idx += 2;
		methods[i].descriptor_index = getU2(&data[idx]); // descriptor_index
		idx += 2;
		methods[i].attributes_count = getU2(&data[idx]); // attributes_count
		idx += 2;

		methods[i].pCode_attr = NULL;
		
		if(methods[i].attributes_count > 0)
		{
			//skip attributes
			for(int a = 0; a < methods[i].attributes_count; a++)
			{
				unsigned short name_index = getU2(&data[idx]);
				idx += 2;
				
				//printf("Attribute name index = %d\n", name_index);
				unsigned int len = getU4(&data[idx]);
				idx += 4;
				idx += len;
			}

			methods[i].pCode_attr = new Code_attribute;
			parseMethodCodeAttribute(i, methods[i].pCode_attr);
		}		
	}
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
void JavaClass::parseAttributeInfo(char* data, int& idx)
{
	attributes = new attribute_info*[attributes_count];
	
	if(methods == NULL) return;
	
	for(int i = 0; i < attributes_count; i++)
	{
		attributes[i] = (attribute_info*)(&data[idx]);
		unsigned short name_index = getU2(&data[idx]); // attribute_name_index
		idx += 2;
		unsigned int len = getU4(&data[idx]); // len
		idx += 4;
		idx += len;
		
		//std::cout << "Attribute name index = " << name_index << std::endl;
	}
}
Ejemplo n.º 9
0
void JavaClass::getStringFromConstPool(int idx, std::string& str)
{
	if(idx < 1 || idx >= constant_pool_count)
		return;
		
	if(constant_pool[idx]->tag != CONSTANT_Utf8)
		return;

	unsigned char *p = (unsigned char*)constant_pool[idx];

	short length = getU2(&p[1]);
	//std::cout << "Length: " << length << std::endl;
	char *buffer = new char[length+1];
	buffer[length] = 0;
	std::memcpy(buffer, &p[3], length);
	str.assign(buffer, length);
	
	delete buffer;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
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;
}
Ejemplo n.º 18
0
Archivo: lwo2.c Proyecto: 2asoft/xray
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;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
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;
}