Exemplo n.º 1
0
void command_prompt(void *pvParameters)
{
	char buf[128];
	char *argv[20];
        char hint[] = USER_NAME "@" USER_NAME "-STM32:~$ ";

	fio_printf(1, "\rWelcome to FreeRTOS Shell\r\n");
	while(1){
		fio_printf(1, "%s", hint);
		fio_read(0, buf, 127);
	
		int n=parse_command(buf, argv);

		/* will return pointer to the command function */
		//if (*argv[0]=='\0')
		cmdfunc *fptr=do_command(argv[0]);
		if(fptr!=NULL)
			fptr(n, argv);
		else if (*argv[0]!='\0')
			fio_printf(2, "\r\n\"%s\" command not found.\r\n", argv[0]);
		else
			fio_printf(1, "\r\n");
	}

}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
    char buf[1024] = {0};
    int fd = open("./fio_read.c", O_RDONLY);
    int ret = fio_read(fd, buf, 1024);
    printf("ret = %d\n", ret);
    return 0;
}
Exemplo n.º 3
0
int model_loadmesh(struct gfx_model_mesh* mesh, file_t f, struct allocator* alloc)
{
	struct h3d_mesh h3dmesh;
    fio_read(f, &h3dmesh, sizeof(h3dmesh), 1);
	mesh->geo_id = h3dmesh.geo_idx;
	mesh->submesh_cnt = h3dmesh.submesh_cnt;
	if (h3dmesh.submesh_cnt > 0)	{
		mesh->submeshes = (struct gfx_model_submesh*)A_ALLOC(alloc,
            sizeof(struct gfx_model_submesh)*h3dmesh.submesh_cnt, MID_GFX);
		if (mesh->submeshes == NULL)
			return FALSE;
		for (uint i = 0; i < h3dmesh.submesh_cnt; i++)	{
			struct h3d_submesh h3dsubmesh;
		    fio_read(f, &h3dsubmesh, sizeof(h3dsubmesh), 1);
			mesh->submeshes[i].mtl_id = h3dsubmesh.mtl_idx;
			mesh->submeshes[i].subset_id = h3dsubmesh.subset_idx;
		}
	}
	return TRUE;
}
Exemplo n.º 4
0
int model_loadocc(struct gfx_model_occ* occ, file_t f, struct allocator* alloc)
{
    struct h3d_occ h3docc;
    fio_read(f, &h3docc, sizeof(struct h3d_occ), 1);

    strcpy(occ->name, h3docc.name);
    occ->tri_cnt = h3docc.tri_cnt;
    occ->vert_cnt = h3docc.vert_cnt;

    occ->indexes = (uint16*)A_ALLOC(alloc, sizeof(uint16)*h3docc.tri_cnt*3, MID_GFX);
    occ->poss = (struct vec3f*)A_ALIGNED_ALLOC(alloc, sizeof(struct vec3f)*h3docc.vert_cnt, MID_GFX);
    if (occ->indexes == NULL || occ->poss == NULL)  {
        err_printn(__FILE__, __LINE__, RET_OUTOFMEMORY);
        return FALSE;
    }

    fio_read(f, occ->indexes, sizeof(uint16), h3docc.tri_cnt*3);
    fio_read(f, occ->poss, sizeof(struct vec3f), h3docc.vert_cnt);
    return TRUE;
}
Exemplo n.º 5
0
int model_loadnode(struct gfx_model_node* node, file_t f, struct allocator* alloc)
{
	struct h3d_node h3dnode;
    fio_read(f, &h3dnode, sizeof(h3dnode), 1);
	strcpy(node->name, h3dnode.name);
    node->name_hash = hash_str(h3dnode.name);
	node->mesh_id = h3dnode.mesh_idx;
	node->child_cnt = h3dnode.child_cnt;
	node->parent_id = h3dnode.parent_idx;

    model_loadmat(&node->local_mat, h3dnode.local_xform);
    aabb_setf(&node->bb, h3dnode.bb_min[0], h3dnode.bb_min[1], h3dnode.bb_min[2],
        h3dnode.bb_max[0], h3dnode.bb_max[1], h3dnode.bb_max[2]);

	if (h3dnode.child_cnt > 0)	{
		node->child_ids = (uint*)A_ALLOC(alloc, sizeof(uint)*h3dnode.child_cnt, MID_GFX);
		if (node->child_ids == NULL)
			return FALSE;
	 fio_read(f, node->child_ids, sizeof(uint), h3dnode.child_cnt);
	}
	return TRUE;
}
Exemplo n.º 6
0
void read_romfs_task(void *pvParameters)
{
	char buf[128];
	size_t count;
	int fd = fs_open("/romfs/test.txt", 0, O_RDONLY);
	do {
		//Read from /romfs/test.txt to buffer
		count = fio_read(fd, buf, sizeof(buf));

		//Write buffer to fd 1 (stdout, through uart)
		fio_write(1, buf, count);
	} while (count);

	while (1);
}
Exemplo n.º 7
0
int model_loadmtl(struct gfx_model_mtl* mtl, file_t f, struct allocator* alloc)
{
	struct h3d_mtl h3dmtl;
    fio_read(f, &h3dmtl, sizeof(h3dmtl), 1);
	color_setf(&mtl->ambient, h3dmtl.ambient[0], h3dmtl.ambient[1], h3dmtl.ambient[2], 1.0f);
	color_setf(&mtl->diffuse, h3dmtl.diffuse[0], h3dmtl.diffuse[1], h3dmtl.diffuse[2], 1.0f);
	color_setf(&mtl->specular, h3dmtl.specular[0], h3dmtl.specular[1], h3dmtl.specular[2], 1.0f);
	color_setf(&mtl->emissive, h3dmtl.emissive[0], h3dmtl.emissive[1], h3dmtl.emissive[2], 1.0f);
	mtl->spec_exp = h3dmtl.spec_exp;
	mtl->spec_intensity = h3dmtl.spec_intensity;
	mtl->opacity = h3dmtl.opacity;
	mtl->map_cnt = h3dmtl.texture_cnt;
	if (h3dmtl.texture_cnt > 0)	{
		mtl->maps = (struct gfx_model_map*)A_ALLOC(alloc,
            sizeof(struct gfx_model_map)*h3dmtl.texture_cnt, MID_GFX);
		if (mtl->maps == NULL)
			return FALSE;
		for (uint i = 0; i < h3dmtl.texture_cnt; i++)	{
			struct h3d_texture h3dtex;
		    fio_read(f, &h3dtex, sizeof(h3dtex), 1);
			/* h3d_texture_type = gfx_model_maptype */
			mtl->maps[i].type = (enum gfx_model_maptype)h3dtex.type;
			strcpy(mtl->maps[i].filepath, h3dtex.filepath);

            /* TODO: this is a workaround for diffuse mapped materials that
             * imports false color values from assimp */
            if (mtl->maps[i].type == GFX_MODEL_DIFFUSEMAP)
                color_setc(&mtl->diffuse, &g_color_white);
		}
	}

	if (mtl->opacity < (1.0f - EPSILON))
		BIT_ADD(mtl->flags, GFX_MODEL_MTLFLAG_TRANSPARENT);

	return TRUE;
}
Exemplo n.º 8
0
int filedump(const char *filename){
	char buf[128];

	int fd=fs_open(filename, 0, O_RDONLY);

	if(fd==OPENFAIL)
		return 0;

	fio_printf(1, "\r\n");

	int count;
	while((count=fio_read(fd, buf, sizeof(buf)))>0){
		fio_write(1, buf, count);
	}

	fio_close(fd);
	return 1;
}
Exemplo n.º 9
0
gfx_buffer model_loadvbuffer(file_t f, uint vert_cnt, uint elem_sz, struct allocator* tmp_alloc,
                             uint thread_id)
{
	uint size = vert_cnt * elem_sz;
    A_SAVE(tmp_alloc);
	void* buf = A_ALLOC(tmp_alloc, size, MID_GFX);
	if (buf == NULL)    {
        A_LOAD(tmp_alloc);
		return NULL;
    }
    fio_read(f, buf, elem_sz, vert_cnt);

	gfx_buffer gbuf = gfx_create_buffer(GFX_BUFFER_VERTEX, GFX_MEMHINT_STATIC, size, buf, thread_id);

    A_FREE(tmp_alloc, buf);
    A_LOAD(tmp_alloc);
	return gbuf;
}
Exemplo n.º 10
0
void command_prompt(void *pvParameters)
{
	char buf[128];
	char *argv[20];
	fio_printf(1, "\rWelcome to FreeRTOS Shell\r\n");
	while(1){
		fio_printf(1, "\r>>");
		fio_read(0, buf, 127);
	
		int n=parse_command(buf, argv);

		/* will return pointer to the command function */
		cmdfunc *fptr=do_command(argv[0]);
		if(fptr!=NULL)
			fptr(n, argv);
		else
			fio_printf(2, "\r\n\"%s\" command not found.\r\n", argv[0]);
	}
}
Exemplo n.º 11
0
/* Display the content of the file specified. */
void cmd_cat( const char *filename )
{
	char buffer[129];
	int fd = fs_open( filename, 0, O_RDONLY ), count;

	if ( fd < 0 )
	{
		sPuts( "The file dose not exist!" );
		return;
	}

	while( ( count = fio_read( fd, buffer, sizeof(buffer) - 1 ) ) > 0 )
	{
		buffer[ count ] = '\0';
		print_to_console( buffer );
	}

	sPuts( "" );
	fio_close( fd );

	return;
}
Exemplo n.º 12
0
static void fill_parameters(struct header_s *h)
{
        rrand_seed(time(NULL), time(NULL) + 2);
        
        h->index_id = rrand();
        h->iblock = iblock;
        h->segment_size = segment_size;

        char *basename = pparm_common_name(dex_names[FW]);
        char *name;
        int fd;

        asprintf(&name, "%s.%u.nfo", basename, iblock);
        if ((fd = open(name, O_RDONLY, 0)) == -1)
                dub_sysdie("Couldn't open file %s", name);

        fio_read(fd, h->fw_layers, sizeof(h->fw_layers));
        close(fd);

        free(name);
        free(basename);
}
Exemplo n.º 13
0
int main()
{
    int whichdrawbuf = 0;
    int s;
    char *buffer;
	int i;
	int size;
	int rc;
	int fd;
    // Initialise RPC system.

    sif_rpc_init(0);
    
    // Setup the Video.

    DmaReset();
    initGraph(3);
    SetVideoMode();
    //install_VRstart_handler();

    // Setup the double buffers.

   // SetDrawFrameBuffer(1);
   // SetDrawFrameBuffer(0);
   // SetCrtFrameBuffer(1);

    // Load the modules!

    loadModules();


    // Loaded the modules.. now try ps2ip now..
    if(ps2ip_init()<0)
	{
		printf("ERROR: ps2ip_init failed2");
		k_SleepThread();
	}
	//put here your file path 
    fd=fio_open("ps2vfs:\\primer\\segun\\mio.txt",O_RDONLY);
	if (fd>0)
	{
		printf("file id kernel is %d \n");
		size=fio_lseek(fd,0,SEEK_END);
		i=fio_lseek(fd,0,SEEK_SET);
		buffer=(char *)malloc(sizeof(char)*size);
		i=fio_read(fd,buffer,size);
		
		printf("receive size:  %d \n",i);
		printf("receive: buffer= %s \n",buffer);
		fio_close(fd);
			
	}
           
	
	

	
	
	while ( 1 )
	{
        //WaitForNextVRstart(1);

        //ClearVRcount();
        //SetCrtFrameBuffer(whichdrawbuf);
        //whichdrawbuf ^= 1;
        //SetDrawFrameBuffer(whichdrawbuf);
//        scr_printf( "t" );
    } 

    // We shouldn't get here.. but just in case.

    k_SleepThread();

}
Exemplo n.º 14
0
struct gfx_model* gfx_model_load(struct allocator* alloc, const char* h3dm_filepath,
    uint thread_id)
{
	struct allocator* tmp_alloc = tsk_get_tmpalloc(thread_id);
	A_SAVE(tmp_alloc);

	struct h3d_header header;
    struct h3d_model h3dmodel;
	struct gfx_model* model = NULL;
    uint renderable_idx = 0;
    struct stack_alloc stack_mem;
    struct allocator stack_alloc;
    result_t r;

    memset(&stack_mem, 0x00, sizeof(stack_mem));

	file_t f = fio_openmem(tmp_alloc, h3dm_filepath, FALSE, MID_GFX);
	if (f == NULL)	{
		err_printf(__FILE__, __LINE__, "load model '%s' failed: could not open file", h3dm_filepath);
		goto err_cleanup;
	}

	/* header */
    fio_read(f, &header, sizeof(header), 1);
	if (header.sign != H3D_SIGN || header.type != H3D_MESH)	{
		err_printf(__FILE__, __LINE__, "load model '%s' failed: invalid file format", h3dm_filepath);
		goto err_cleanup;
	}

    if (header.version != H3D_VERSION && header.version != H3D_VERSION_13)  {
        err_printf(__FILE__, __LINE__, "load model '%s' failed: file version not implemented/obsolete",
            h3dm_filepath);
        goto err_cleanup;
    }

    /* model */
    fio_read(f, &h3dmodel, sizeof(h3dmodel), 1);

    /* calculate size and create stack allocator for proceeding allocations */
    size_t total_sz =
        sizeof(struct gfx_model) +
        h3dmodel.node_cnt*sizeof(struct gfx_model_node) + 16 +
        h3dmodel.node_cnt*sizeof(uint) +
        h3dmodel.geo_cnt*sizeof(struct gfx_model_geo) +
        h3dmodel.mesh_cnt*sizeof(struct gfx_model_mesh) +
        h3dmodel.mtl_cnt*sizeof(struct gfx_model_mtl) +
        h3dmodel.has_occ*sizeof(struct gfx_model_occ) +
        h3dmodel.total_childidxs*sizeof(uint) +
        h3dmodel.total_geo_subsets*sizeof(struct gfx_model_geosubset) +
        h3dmodel.total_joints*sizeof(struct gfx_model_joint) +
        h3dmodel.total_joints*sizeof(struct mat3f) +
        h3dmodel.total_submeshes*sizeof(struct gfx_model_submesh) +
        h3dmodel.total_skeletons*sizeof(struct gfx_model_skeleton) +
        h3dmodel.total_skeletons*32 + /* 2 aligned allocs per skeleton */
        h3dmodel.total_maps*sizeof(struct gfx_model_map) +
        h3dmodel.occ_idx_cnt*sizeof(uint16) +
        h3dmodel.occ_vert_cnt*sizeof(struct vec3f) +
        h3dmodel.has_occ*16; /* 1 aligned alloc for occ */
    r = mem_stack_create(alloc, &stack_mem, total_sz, MID_GFX);
    if (IS_FAIL(r)) {
        err_printn(__FILE__, __LINE__, RET_OUTOFMEMORY);
        goto err_cleanup;
    }
    mem_stack_bindalloc(&stack_mem, &stack_alloc);

    /* */
    model = (struct gfx_model*)A_ALLOC(&stack_alloc, sizeof(struct gfx_model), MID_GFX);
    if (model == NULL)	{
        err_printn(__FILE__, __LINE__, RET_OUTOFMEMORY);
        goto err_cleanup;
    }
    memset(model, 0x00, sizeof(struct gfx_model));
    model->alloc = alloc;

	/* nodes */
	if (h3dmodel.node_cnt > 0)	{
		model->nodes = (struct gfx_model_node*)A_ALIGNED_ALLOC(&stack_alloc,
            sizeof(struct gfx_model_node)*h3dmodel.node_cnt, MID_GFX);
        ASSERT(model->nodes);
		memset(model->nodes, 0x00, sizeof(struct gfx_model_node)*h3dmodel.node_cnt);

		for (uint i = 0; i < h3dmodel.node_cnt; i++)	{
			struct gfx_model_node* node = &model->nodes[i];
			if (!model_loadnode(node, f, &stack_alloc))
				goto err_cleanup;

            /* NOTE: we set root matrix to identity and keep the old one as "root_mat" */
            if (i == 0) {
                mat3_setm(&model->root_mat, &node->local_mat);
                mat3_set_ident(&node->local_mat);
            }
			model->node_cnt ++;
		}
	}

	/* meshes */
	if (h3dmodel.mesh_cnt > 0)	{
		model->meshes = (struct gfx_model_mesh*)A_ALLOC(&stack_alloc,
            sizeof(struct gfx_model_mesh)*h3dmodel.mesh_cnt, MID_GFX);
		ASSERT(model->meshes);
		memset(model->meshes, 0x00, sizeof(struct gfx_model_mesh)*h3dmodel.mesh_cnt);
		uint idx = 0;

		for (uint i = 0; i < h3dmodel.mesh_cnt; i++)	{
			struct gfx_model_mesh* mesh = &model->meshes[i];
			if (!model_loadmesh(mesh, f, &stack_alloc))
				goto err_cleanup;

			/* assign global indexes */
			for (uint k = 0; k < mesh->submesh_cnt; k++)
				mesh->submeshes[k].offset_idx = idx++;

			model->mesh_cnt ++;
		}
	}

	/* geos */
	if (h3dmodel.geo_cnt > 0)	{
		model->geos = (struct gfx_model_geo*)A_ALLOC(&stack_alloc,
            sizeof(struct gfx_model_geo)*h3dmodel.geo_cnt, MID_GFX);
		ASSERT(model->geos);

		memset(model->geos, 0x00, sizeof(struct gfx_model_geo)*h3dmodel.geo_cnt);
		for (uint i = 0; i < h3dmodel.geo_cnt; i++)	{
			struct gfx_model_geo* geo = &model->geos[i];
			if (!model_loadgeo(geo, f, &stack_alloc, tmp_alloc, thread_id))
				goto err_cleanup;
			model->geo_cnt ++;
		}
	}

	/* materials */
	if (h3dmodel.mtl_cnt > 0)	{
		model->mtls = (struct gfx_model_mtl*)A_ALLOC(&stack_alloc,
            sizeof(struct gfx_model_mtl)*h3dmodel.mtl_cnt, MID_GFX);
		ASSERT(model->mtls);

		memset(model->mtls, 0x00, sizeof(struct gfx_model_mtl)*h3dmodel.mtl_cnt);
		for (uint i = 0; i < h3dmodel.mtl_cnt; i++)	{
			struct gfx_model_mtl* mtl = &model->mtls[i];
			if (!model_loadmtl(mtl, f, &stack_alloc))
                goto err_cleanup;
			model->mtl_cnt ++;
		}
	}

    if (header.version >= H3D_VERSION_11 && h3dmodel.has_occ)   {
        model->occ = (struct gfx_model_occ*)A_ALLOC(&stack_alloc, sizeof(struct gfx_model_occ),
            MID_GFX);
        ASSERT(model->occ);

        memset(model->occ, 0x00, sizeof(struct gfx_model_occ));
        if (!model_loadocc(model->occ, f, &stack_alloc))
            goto err_cleanup;
    }

    /* populate renderable nodes */
    model->renderable_idxs = (uint*)A_ALLOC(&stack_alloc, sizeof(uint)*h3dmodel.node_cnt,
        MID_GFX);
    ASSERT(model->renderable_idxs);

    for (uint i = 0; i < h3dmodel.node_cnt; i++)	{
        struct gfx_model_node* node = &model->nodes[i];
        if (node->mesh_id != INVALID_INDEX)
            model->renderable_idxs[renderable_idx++] = i;
    }
    model->renderable_cnt = renderable_idx;

    /* calculate sum of aabb(s) from renderable nodes */
	aabb_setzero(&model->bb);
    struct mat3f node_mat;  /* transform matrix, relative to model */
	for (uint i = 0; i < renderable_idx; i++)   {
        struct gfx_model_node* node = &model->nodes[model->renderable_idxs[i]];
        mat3_setm(&node_mat, &node->local_mat);
        struct gfx_model_node* pnode = node;
        while (pnode->parent_id != INVALID_INDEX)	{
            pnode = &model->nodes[pnode->parent_id];
            mat3_mul(&node_mat, &node_mat, &pnode->local_mat);
        }
        if (node->parent_id != INVALID_INDEX)
            mat3_mul(&node_mat, &node_mat, &model->root_mat);

        /* transform local box to model-relative bounding box and merge with final */
        struct aabb bb;
        aabb_xform(&bb, &model->nodes[model->renderable_idxs[i]].bb, &node_mat);
		aabb_merge(&model->bb, &model->bb, &bb);
    }
    /* for empty models, we set a minimal bounding-box */
    if (aabb_iszero(&model->bb))    {
        aabb_pushptf(&model->bb, 0.1f, 0.1f, 0.1f);
        aabb_pushptf(&model->bb, -0.1f, -0.1f, -0.1f);
    }

    fio_close(f);
	A_LOAD(tmp_alloc);

    if (thread_id != 0) {
        gfx_delayed_waitforobjects(thread_id);
        gfx_delayed_fillobjects(thread_id);
    }

	return model;

err_cleanup:
	if (f != NULL)
        fio_close(f);
	if (model != NULL)
		gfx_model_unload(model);
    mem_stack_destroy(&stack_mem);
	A_LOAD(tmp_alloc);
	return NULL;
}
Exemplo n.º 15
0
int model_loadgeo(struct gfx_model_geo* geo, file_t f, struct allocator* alloc,
		struct allocator* tmp_alloc, uint thread_id)
{
	struct h3d_geo h3dgeo;
	uint v_cnt = 0;

    fio_read(f, &h3dgeo, sizeof(h3dgeo), 1);
	geo->vert_cnt = h3dgeo.vert_cnt;
	geo->vert_id_cnt = h3dgeo.vert_id_cnt;
	geo->tri_cnt = h3dgeo.tri_cnt;
	geo->subset_cnt = h3dgeo.subset_cnt;
	geo->ib_type = h3dgeo.ib_isui32 ? GFX_INDEX_UINT32 : GFX_INDEX_UINT16;
	memcpy(geo->vert_ids, h3dgeo.vert_ids, sizeof(h3dgeo.vert_ids));

	/* subsets */
	ASSERT(h3dgeo.subset_cnt > 0);
	geo->subsets = (struct gfx_model_geosubset*)A_ALLOC(alloc,
        sizeof(struct gfx_model_geosubset)*h3dgeo.subset_cnt, MID_GFX);
	ASSERT(geo->subsets != NULL);

	for (uint i = 0; i < h3dgeo.subset_cnt; i++)	{
		struct h3d_geo_subset h3dsubset;
	    fio_read(f, &h3dsubset, sizeof(h3dsubset), 1);
		geo->subsets[i].ib_idx = h3dsubset.ib_idx;
		geo->subsets[i].idx_cnt = h3dsubset.idx_cnt;
	}

	/* indexes */
	ASSERT(h3dgeo.tri_cnt > 0);
	uint ibuffer_sz = (geo->ib_type == GFX_INDEX_UINT16) ? sizeof(uint16)*h3dgeo.tri_cnt*3 :
			sizeof(uint)*h3dgeo.tri_cnt*3;
	void* indexes = A_ALLOC(tmp_alloc, ibuffer_sz, MID_GFX);
	if (indexes == NULL)
		goto err_cleanup;

    fio_read(f, indexes, ibuffer_sz, 1);

 	geo->ibuffer = gfx_create_buffer(GFX_BUFFER_INDEX, GFX_MEMHINT_STATIC, ibuffer_sz, indexes,
        thread_id);
	A_FREE(tmp_alloc, indexes);
	if (geo->ibuffer == NULL)
		goto err_cleanup;

	/* vertices */
	/* base data */
    int has_pos = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_POSITION);
    int has_norm = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_NORMAL);
    int has_coord = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_TEXCOORD0);

	if (has_pos | has_norm | has_coord)	{
		geo->vbuffers[GFX_MODEL_BUFFER_BASE] =
				model_loadvbuffer(f, h3dgeo.vert_cnt, sizeof(struct h3d_vertex_base), tmp_alloc,
                thread_id);
		if (geo->vbuffers[GFX_MODEL_BUFFER_BASE] == NULL)
			goto err_cleanup;
	}
    geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_POSITION;
	if (has_norm)
		geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_NORMAL;
	if (has_coord)
		geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_TEXCOORD0;

    /* skin data */
    int has_bindex = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_BLENDINDEX);
    int has_bweight = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_BLENDWEIGHT);
    if (has_bindex | has_bweight)   {
        geo->vbuffers[GFX_MODEL_BUFFER_SKIN] = model_loadvbuffer(f, h3dgeo.vert_cnt,
            sizeof(struct h3d_vertex_skin), tmp_alloc, thread_id);
        if (geo->vbuffers[GFX_MODEL_BUFFER_BASE] == NULL)
            goto err_cleanup;
    }

    if (has_bindex)
        geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_BLENDINDEX;
    if (has_bweight)
        geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_BLENDWEIGHT;

    /* normal-map coord data */
    int has_tangent = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_TANGENT);
    int has_binorm = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_BINORMAL);
    if (has_tangent | has_binorm)   {
        geo->vbuffers[GFX_MODEL_BUFFER_NMAP] = model_loadvbuffer(f, h3dgeo.vert_cnt,
            sizeof(struct h3d_vertex_nmap), tmp_alloc, thread_id);
        if (geo->vbuffers[GFX_MODEL_BUFFER_NMAP] == NULL)
            goto err_cleanup;
    }
    if (has_tangent)
        geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_TANGENT;
    if (has_binorm)
        geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_BINORMAL;

    /* Extra data */
    int has_coord1 = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_TEXCOORD1);
    int has_color = model_checkvertid(h3dgeo.vert_ids, h3dgeo.vert_id_cnt,
        GFX_INPUTELEMENT_ID_COLOR);
    if (has_coord1 | has_color) {
        geo->vbuffers[GFX_MODEL_BUFFER_EXTRA] = model_loadvbuffer(f, h3dgeo.vert_cnt,
            sizeof(struct h3d_vertex_extra), tmp_alloc, thread_id);
        if (geo->vbuffers[GFX_MODEL_BUFFER_EXTRA] == NULL)
            goto err_cleanup;
    }
	if (has_coord1)
		geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_TEXCOORD1;
	if (has_color)
		geo->vert_ids[v_cnt++] = GFX_INPUTELEMENT_ID_COLOR;

	/* skeleton */
	if (h3dgeo.joint_cnt > 0)	{
		geo->skeleton = (struct gfx_model_skeleton*)A_ALLOC(alloc,
            sizeof(struct gfx_model_skeleton), MID_GFX);
		if (geo->skeleton == NULL)
			return FALSE;
		memset(geo->skeleton, 0x00, sizeof(struct gfx_model_skeleton));
		geo->skeleton->joint_cnt = h3dgeo.joint_cnt;
		geo->skeleton->bones_pervertex_max = h3dgeo.bones_pervertex_max;
        model_loadmat(&geo->skeleton->joints_rootmat, h3dgeo.joints_rootmat);

		geo->skeleton->init_pose = (struct mat3f*)A_ALIGNED_ALLOC(alloc,
            sizeof(struct mat3f)*h3dgeo.joint_cnt, MID_GFX);
		geo->skeleton->joints = (struct gfx_model_joint*)A_ALIGNED_ALLOC(alloc,
				sizeof(struct gfx_model_joint)*h3dgeo.joint_cnt, MID_GFX);
		ASSERT(geo->skeleton->init_pose != NULL);
        ASSERT(geo->skeleton->joints != NULL);

		for (uint i = 0; i < h3dgeo.joint_cnt; i++)	{
			struct h3d_joint h3djoint;
			struct gfx_model_joint* joint = &geo->skeleton->joints[i];
		    fio_read(f, &h3djoint, sizeof(h3djoint), 1);

			strcpy(joint->name, h3djoint.name);
            joint->name_hash = hash_str(h3djoint.name);

            model_loadmat(&joint->offset_mat, h3djoint.offset_mat);

			joint->parent_id = h3djoint.parent_idx;
		}

        fio_read(f, geo->skeleton->init_pose, sizeof(struct mat3f), h3dgeo.joint_cnt);
	}

    ASSERT(v_cnt > 0);

    /* input layout */
    uint buff_cnt = 0;
    uint input_cnt = geo->vert_id_cnt;
    struct gfx_input_vbuff_desc vbuffs[GFX_MODEL_BUFFER_CNT];
    struct gfx_input_element_binding inputs[GFX_INPUTELEMENT_ID_CNT];

    for (uint i = 0; i < input_cnt; i++)  {
        inputs[i].id = (enum gfx_input_element_id)geo->vert_ids[i];
        inputs[i].vb_idx = gfx_model_choose_elem_buffidx(inputs[i].id, &inputs[i].elem_offset);
    }

    for (uint i = 0; i < GFX_MODEL_BUFFER_CNT; i++)   {
        if (geo->vbuffers[i] != NULL)   {
            vbuffs[buff_cnt].stride = gfx_model_choose_vbuff_size(i);
            vbuffs[buff_cnt].vbuff = geo->vbuffers[i];
            buff_cnt ++;
        }
    }

    geo->inputlayout = gfx_create_inputlayout(vbuffs, buff_cnt, inputs, input_cnt,
        geo->ibuffer, geo->ib_type, thread_id);
	if (geo->inputlayout == NULL)
		goto err_cleanup;

	return TRUE;

err_cleanup:
	if (geo != NULL)
		model_unloadgeo(geo);
	return FALSE;
}