Beispiel #1
0
void save_pak(struct paki_args* args)
{
    result_t r;
    struct pak_file pak;

    path_norm(args->pakfile, args->pakfile);
    path_norm(args->path, args->path);

    r = pak_create(&pak, mem_heap(), args->pakfile, args->compress_mode, 0);
    if (IS_FAIL(r))     {
        err_sendtolog(FALSE);
        return;
    }


    r = compress_directory(&pak, args, "");
    if (IS_FAIL(r))     {
        err_sendtolog(FALSE);
        pak_close(&pak);
        return;
    }

    pak_close(&pak);

    // report
    printf(TERM_BOLDWHITE "Saved pak: '%s'\nTotal %d file(s) - %d Error(s), %d Warning(s)\n" TERM_RESET,
           args->pakfile, args->file_cnt, args->err_cnt, args->warn_cnt);
}
Beispiel #2
0
void load_pak(struct paki_args* args)
{
    result_t r;
    struct pak_file pak;
    char filename[DH_PATH_MAX];

    path_norm(args->pakfile, args->pakfile);
    path_tounix(args->path, args->path);

    r = pak_open(&pak, mem_heap(), args->pakfile, 0);
    if (IS_FAIL(r))     {
        err_sendtolog(FALSE);
        return;
    }

    uint file_id = pak_findfile(&pak, args->path);
    if (file_id == INVALID_INDEX)   {
        printf(TERM_BOLDRED "Extract failed: file '%s' not found in pak.\n" TERM_RESET, args->path);
        pak_close(&pak);
        return;
    }

    path_getfullfilename(filename, args->path);
    file_t f = fio_createdisk(filename);
    if (f == NULL)     {
        printf(TERM_BOLDRED "Extract failed: could not create '%s' for writing.\n" TERM_RESET,
               filename);
        pak_close(&pak);
        err_sendtolog(FALSE);
        return;
    }

    file_t src_file = pak_getfile(&pak, mem_heap(), mem_heap(), file_id, 0);
    if (src_file == NULL)   {
        pak_close(&pak);
        fio_close(f);
        err_sendtolog(FALSE);
        return;
    }

    size_t size;
    struct allocator* alloc;
    void* buffer = fio_detachmem(src_file, &size, &alloc);
    fio_write(f, buffer, size, 1);
    A_FREE(alloc, buffer);
    fio_close(f);

    pak_close(&pak);

    if (BIT_CHECK(args->usage, PAKI_USAGE_VERBOSE)) {
        printf(TERM_WHITE "%s -> %s\n" TERM_RESET, args->path, filename);
    }
    args->file_cnt ++;

    // report
    printf(TERM_BOLDWHITE "Finished: total %d file(s) - %d error(s), %d warning(s)\n" TERM_RESET,
           args->file_cnt, args->err_cnt, args->warn_cnt);
}
Beispiel #3
0
void GLSL_LoadShader(GLuint *shader_id,char *filename, int type)
{
    PFILE *f;
    int filesize;
    int bytes;
    char * buffer;
    int wasok;

    if(!EXTGL_shading_language)
    {
     *shader_id=0;
     sprintf (FANTASY_DEBUG_STRING, "Sorry, this card does not support GLSL\n");
     Debug(DEBUG_LEVEL_WARNING);
     return;
    } 

    f = pak_open(filename, "rb");
    if (f == NULL)
    {
     sprintf (FANTASY_DEBUG_STRING, "Shader file %s not found\n",filename);
     Debug(DEBUG_LEVEL_ERROR);
     *shader_id=0;     
     return;
    }

    // Find file size.
    pak_fseek(f, 0, SEEK_END);
    filesize = pak_ftell(f);
    pak_fseek(f, 0, SEEK_SET);

    buffer = (char *)malloc(filesize*sizeof(char)+1);
    if(!buffer) return;
    // Leemos el shader en memoria y lo almacenamos
    bytes = pak_read(buffer,1,filesize,f);
    pak_close(f);
    buffer[filesize*sizeof(char)] = '\0';

    // Create shader
    if(type == GLSL_VERTEX_SHADER)
       *shader_id = f_glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );
    else if (type == GLSL_FRAGMENT_SHADER)
       *shader_id = f_glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB );
    
    // Compile shader
    f_glShaderSourceARB( *shader_id, 1, (const char **)&buffer, NULL );
    f_glCompileShaderARB( *shader_id);
    // Check for errors
    f_glGetObjectParameterivARB( *shader_id, GL_OBJECT_COMPILE_STATUS_ARB,&wasok);
    if( !wasok )
    {
	f_glGetInfoLogARB(*shader_id, sizeof(errorString), NULL, errorString);
        sprintf (FANTASY_DEBUG_STRING, "Error compiling shader %s\n",filename);
        Debug(DEBUG_LEVEL_ERROR);	
        sprintf (FANTASY_DEBUG_STRING, "%s\n",errorString);
        Debug(DEBUG_LEVEL_ERROR);	
	*shader_id=0;
	return;
    }
    free(buffer);
}
Beispiel #4
0
void list_pak(struct paki_args* args)
{
    result_t r;
    struct pak_file pak;
    r = pak_open(&pak, mem_heap(), args->pakfile, 0);
    if (IS_FAIL(r))     {
        err_sendtolog(FALSE);
        return;
    }

    uint cnt = INVALID_INDEX;
    char* filelist = pak_createfilelist(&pak, mem_heap(), &cnt);
    pak_close(&pak);
    if (cnt == 0)	{
        printf(TERM_BOLDWHITE "There are no files in the pak '%s'.\n" TERM_RESET, args->pakfile);
        return;
    }

    if (filelist == NULL)	{
        printf(TERM_BOLDRED "Not enough memory.\n" TERM_RESET);
        return;
    }

    for (uint i = 0; i < cnt; i++)	{
        printf(TERM_WHITE "%s\n" TERM_RESET, filelist + i*DH_PATH_MAX);
    }
    printf(TERM_BOLDWHITE "Total %d files in '%s'.\n" TERM_RESET, cnt, args->pakfile);
    FREE(filelist);
}
Beispiel #5
0
TSpline *SPLINE_New (char *filename)
{
    int      i;
    PFILE   *fp;
    TSpline *spl;
    char     magic[5];

    fp = pak_open (filename, "rb");
    assert (fp != NULL);

    // Check magic
    pak_read (magic, 1, 4, fp);
    magic[4] = '\0';
    assert (!strcmp (magic, magic_binpoly));

    spl = (TSpline *) malloc (sizeof (TSpline));
    assert (spl != NULL);
    spl->tfactor = 1.0f;

    // Number of nodes => number of polynomials = nodes + 1
    pak_read (&spl->nkeys, 4, 1, fp);
    assert (spl->nkeys != 0);

    spl->p = (TKey *) malloc ((spl->nkeys + 1) * sizeof (TKey));
    assert (spl->p != NULL);

    for (i=0; i<spl->nkeys; i++)
    {
        // Read time
        pak_read (&spl->p[i].t, 4, 1, fp);

        // Read polynomial coefficients
        pak_read (spl->p[i].c, 4, 4, fp);
    }

    // Last polynomial
    spl->p[i].c[0] = 0.0f;
    spl->p[i].c[1] = 0.0f;
    spl->p[i].c[2] = 0.0f;
    pak_read (&spl->p[i].t, 4, 1, fp);
    pak_read (&spl->p[i].c[3], 4, 1, fp);

    spl->nkeys ++;

    pak_close (fp);

    spl->t0 = spl->p[0].t;
    spl->t1 = spl->p[i].t;

    //spl->loop_mode = SPLINE_LOOP_CONSTANT;
    //spl->loop_mode = SPLINE_LOOP_CONTINUITY;
    spl->loop_mode = SPLINE_LOOP_MOD;

    return spl;
}
Beispiel #6
0
void eng_release()
{
    if (g_eng == NULL)
        return;

    rs_release_resources();

    lod_releasemgr();
#if !defined(_DEBUG_)
    pak_close(&g_eng->data_pak);
#endif
	prf_releasemgr();
    sct_release();
    wld_releasemgr();
    scn_releasemgr();
    cmp_releasemgr();
    phx_release();
    hud_release();
    gfx_release();
    rs_reportleaks();
    rs_releasemgr();
    tsk_releasemgr();

    if (g_eng->timer != NULL)
        timer_destroyinstance(g_eng->timer);

    /* check for main memory leaks */
    if (BIT_CHECK(g_eng->params.flags, ENG_FLAG_DEV))    {
        int leak_cnt = mem_freelist_getleaks(&g_eng->data_freelist, NULL);
        if (leak_cnt > 0)
            log_printf(LOG_WARNING, "%d leaks found on dynamic 'data' memory", leak_cnt);
    }

    mem_freelist_destroy(&g_eng->data_freelist);
    mem_stack_destroy(&g_eng->lsr_stack);

    log_print(LOG_TEXT, "engine released.");

	if (BIT_CHECK(g_eng->params.flags, ENG_FLAG_CONSOLE))	{
		log_outputfunc(FALSE, NULL, NULL);
		con_release();
	}

    FREE(g_eng);
    g_eng = NULL;
}
Beispiel #7
0
static VFS_VOID pak_plugin_archive_close( vfs_archive archive)
{
    pak_close((pak*)archive);
}
Beispiel #8
0
void make_pak(char *input, char *output, bool compress, bool verbose) {

    time_last = time(NULL);
    DIR* dir;
    struct dirent * dent;
    char* basepath = input;
    dir = opendir(basepath);
    if (!dir) {
        exit(EXIT_FAILURE);
    }

    pak_handle_t* handle = pak_open_write(output);

    printf("Building entry, string and data files...");
    fflush(stdout);

    char dataTempNam[FILENAME_MAX];
    gen_random(dataTempNam, 44);
    char dataTempPath[FILENAME_MAX];
    memset(dataTempPath, 0, FILENAME_MAX);
    sprintf(dataTempPath, "/tmp/%s.data", dataTempNam);
    char stringTempPath[FILENAME_MAX];
    memset(stringTempPath, 0, FILENAME_MAX);
    sprintf(stringTempPath, "/tmp/%s.string", dataTempNam);
    char entryTempPath[FILENAME_MAX];
    memset(entryTempPath, 0, FILENAME_MAX);
    sprintf(entryTempPath, "/tmp/%s.entry", dataTempNam);
    FILE* dataFile = fopen(dataTempPath, "wb");
    FILE* entryFile  = fopen(entryTempPath, "wb");
    FILE* stringFile = fopen(stringTempPath, "wb");

    uint64_t idx = 0;
    while ((dent = readdir(dir)) != NULL)
    {
        if ((time(NULL) - time_last) > 1)
        {
            printf(".");
            fflush(stdout);
            time_last = time(NULL);
        }
        if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
            continue;

        curpath[0] = '\0';
        strcat(curpath, basepath);
        idx = pak_file_or_dir(dent, idx, entryFile, stringFile, dataFile, compress, verbose);
    }

    printf("\nBuilding pak...\n");
    closedir(dir);
    fclose(dataFile);
    fclose(stringFile);
    fclose(entryFile);

    // now to build the file
    // first reopen the temp data
    struct stat64 st;
    entryFile = fopen(entryTempPath, "rb");
    stringFile = fopen(stringTempPath, "rb");
    dataFile = fopen(dataTempPath, "rb");

    // read entry table
    stat64(entryTempPath, &st);
    size_t entryTableSize = st.st_size;
    size_t entryCount = entryTableSize / sizeof(pak_entry_t);
    char* entryTableBuf = malloc(entryTableSize);
    fread(entryTableBuf, 1, entryTableSize, entryFile);

    // read string table
    stat64(stringTempPath, &st);
    size_t stringTableSize = st.st_size;
    char* stringTableBuf = malloc(stringTableSize);
    fread(stringTableBuf, 1, stringTableSize, stringFile);

    // read data table
    stat64(dataTempPath, &st);
    size_t dataTableSize = st.st_size;

    // close files
    fclose(entryFile);
    fclose(stringFile);

    // TODO: Make this manageable
    pak_set_entry_start(handle, (sizeof(pak_header_t) + 31) & ~31);
    pak_set_entry_count(handle, entryCount);
    pak_set_string_table_offset(handle, (handle->header->entry_start + entryTableSize + 31) & ~31);
    pak_set_string_table_size(handle, stringTableSize);
    pak_set_data_offset(handle, (handle->header->string_table_offset + stringTableSize + 31) & ~31);

    // pad buffers
    size_t paddedEntryBufSize = (entryTableSize + 31) & ~31;
    char* paddedEntryBuf = malloc(paddedEntryBufSize);
    pak_clear(paddedEntryBuf, paddedEntryBufSize);
    memcpy(paddedEntryBuf, entryTableBuf, entryTableSize);
    free(entryTableBuf);

    size_t paddedStringBufSize = (stringTableSize + 31) & ~31;
    char* paddedStringBuf = malloc(paddedStringBufSize);

    pak_clear(paddedStringBuf, paddedStringBufSize);
    memcpy(paddedStringBuf, stringTableBuf, stringTableSize);
    free(stringTableBuf);

    // write pak
    FILE* pak = handle->file;
    if (pak)
    {
        fwrite(handle->header, 1, sizeof(pak_header_t), pak);
        fseeko64(pak, (sizeof(pak_header_t) + 31) & ~31, SEEK_SET);
        fwrite(paddedEntryBuf, 1, paddedEntryBufSize, pak);
        fwrite(paddedStringBuf, 1, paddedStringBufSize, pak);

        size_t bytesRead = 0;
        size_t blockSize = BUF_SIZ;
        while(bytesRead < dataTableSize)
        {
            if (blockSize > dataTableSize - bytesRead)
                blockSize = dataTableSize - bytesRead;
            char buf[blockSize];
            size_t nextReadSize = fread(buf, 1, blockSize, dataFile);
            if (nextReadSize <= 0)
                break;  // error or early EOF!

            fwrite(buf, 1, nextReadSize, pak);
            bytesRead += nextReadSize;
        }
    }

    fclose(dataFile);

    printf("Stored %" PRIu64 " files (%s)\n", pak_get_entry_count(handle), (compress ? "compressed" : "uncompressed"));
    pak_close(handle);
    free(paddedEntryBuf);
    free(paddedStringBuf);
    remove(entryTempPath);
    remove(stringTempPath);
    remove(dataTempPath);
}
Beispiel #9
0
int main(int argc, char **argv) {
    bool          extract   = true;
    char         *redirout  = (char*)stdout;
    char         *redirerr  = (char*)stderr;
    char         *file      = NULL;
    char        **files     = NULL;
    pak_file_t   *pak       = NULL;
    size_t        iter      = 0;

    con_init();

    /*
     * Command line option parsing commences now We only need to support
     * a few things in the test suite.
     */
    while (argc > 1) {
        ++argv;
        --argc;

        if (argv[0][0] == '-') {
            if (parsecmd("redirout",  &argc, &argv, &redirout,  1, false))
                continue;
            if (parsecmd("redirerr",  &argc, &argv, &redirerr,  1, false))
                continue;
            if (parsecmd("file",      &argc, &argv, &file,      1, false))
                continue;

            con_change(redirout, redirerr);

            switch (argv[0][1]) {
                case 'e': extract = true;  continue;
                case 'c': extract = false; continue;
            }

            if (!strcmp(argv[0]+1, "debug")) {
                OPTS_OPTION_BOOL(OPTION_DEBUG) = true;
                continue;
            }
            if (!strcmp(argv[0]+1, "memchk")) {
                OPTS_OPTION_BOOL(OPTION_MEMCHK) = true;
                continue;
            }
            if (!strcmp(argv[0]+1, "nocolor")) {
                con_color(0);
                continue;
            }
        }

        vec_push(files, argv[0]);
    }
    con_change(redirout, redirerr);


    if (!file) {
        con_err("-file must be specified for output/input PAK file\n");
        vec_free(files);
        return EXIT_FAILURE;
    }

    if (extract) {
        if (!(pak = pak_open(file, "r"))) {
            con_err("failed to open PAK file %s\n", file);
            vec_free(files);
            return EXIT_FAILURE;
        }

        if (!pak_extract_all(pak, "./")) {
            con_err("failed to extract PAK %s (files may be missing)\n", file);
            pak_close(pak);
            vec_free(files);
            return EXIT_FAILURE;
        }

        /* not possible */
        pak_close(pak);
        vec_free(files);
        stat_info();

        return EXIT_SUCCESS;
    }

    if (!(pak = pak_open(file, "w"))) {
        con_err("failed to open PAK %s for writing\n", file);
        vec_free(files);
        return EXIT_FAILURE;
    }

    for (iter = 0; iter < vec_size(files); iter++) {
        if (!(pak_insert_one(pak, files[iter]))) {
            con_err("failed inserting %s for PAK %s\n", files[iter], file);
            pak_close(pak);
            vec_free(files);
            return EXIT_FAILURE;
        }
    }

    /* not possible */
    pak_close(pak);
    vec_free(files);

    stat_info();
    return EXIT_SUCCESS;
}
Beispiel #10
0
int Material::MatReader(char *filename)
{
 material *matpointer=NULL;
 PFILE *p;
 char cadena[256];
 char cadena2[256];
 char texname[256];
 char *token;
 char separadores [] = " \t";
 int i,j;
 int nmats=0; 			// Number of materials
 int curmat=0;			// Material currently being loaded
 int ntextures;


 p = pak_open(filename,"r");
 if(!p) return -1;


 while(pak_fgets(cadena,256,p))
 {

  if((cadena[0] == '\n') || (cadena[0] == '#')) continue; // Saltamos comentarios y líneas en blanco
  token = strtok(cadena,separadores);
  token2string(token,cadena2);

   if(!strcmp(cadena2,"nmaterials"))  // Leemos el número de materiales y seguimos
   {
    token = strtok(NULL,separadores);
    token2string(token,cadena2);
    nmats = atoi(cadena2);
    matpointer = (material *) malloc(nmats * sizeof(material));    
    if(!matpointer) return -1;
    
    continue;
   }
   else	  // En este caso hemos cogido el nombre de un material
   {
    if(!nmats)
    {
     sprintf (FANTASY_DEBUG_STRING, "Fallo al leer el fichero %s\n",filename);
     Debug(DEBUG_LEVEL_ERROR);
     return -1;
    }

    if(curmat >= nmats)
    {     
       sprintf (FANTASY_DEBUG_STRING, "Error en el archivo %s. Tenemos más materiales de los definidos en nmats\n",filename);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
    }
    // Inicializamos algunos valores por defecto
    matpointer[curmat].specular[0] = matpointer[curmat].specular[1] = matpointer[curmat].specular[2] = 0.0f;
    matpointer[curmat].emission[0] = matpointer[curmat].emission[1] = matpointer[curmat].emission[2] = 0.0f;
    matpointer[curmat].specular[3] = 1.0f;
    matpointer[curmat].emission[3] = 1.0f;
    matpointer[curmat].shininess = 0.0f;
    // Empezamos con la juerga!     
    
    strcpy(matpointer[curmat].matname,cadena2);
    token = strtok(NULL,separadores);	 // Ahora leemos si es estático o dinámico
    token2string(token,cadena2);

    if(!strcmp(cadena2,"static")) 	// Material estático
    {
     matpointer[curmat].shader_based = 0;
    }
    else if(!strcmp(cadena2,"shader")) // Shader based material 
    {
        matpointer[curmat].shader_based = 1;
    }
    else
    {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. No es static ni shader\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
    }

    // En caso de ser un shader, lo siguiente son los ficheros de los shader
    if(matpointer[curmat].shader_based == 1 )
    {
      token = strtok(NULL,separadores);
      token2string(token,cadena2);
      
      if(strcmp(cadena2,"standard")) // If shader_name == "standard", we are using the opengl pipeline
      	GLSL_LoadShader(&(matpointer[curmat].shader.vertexShader),cadena2, GLSL_VERTEX_SHADER);
      else
        matpointer[curmat].shader.vertexShader = 0;
       
      token = strtok(NULL,separadores);
      token2string(token,cadena2);
      
      // There must always be a fragment shader      
      GLSL_LoadShader(&(matpointer[curmat].shader.fragmentShader),cadena2, GLSL_FRAGMENT_SHADER);
      
      // CompileandLinkShader...	      
      GLSL_CompileAndLinkShader(&(matpointer[curmat].shader.programObj),
      				matpointer[curmat].shader.vertexShader,
      				matpointer[curmat].shader.fragmentShader);      
      // GetBasicUniforms
      GLSL_GetUniforms(&(matpointer[curmat]));
      
      matpointer[curmat].shader.params.used=0; // no custom parameters to the shader

    } 
    else // No shader, so let's fill the variables...
    {
    	matpointer[curmat].shader.vertexShader = 0;
    	matpointer[curmat].shader.fragmentShader = 0;
    	matpointer[curmat].shader.programObj = 0;
    }
     token = strtok(NULL,separadores);	 // Ahora leemos si es opaco o transparente
     token2string(token,cadena2);
     if(!strcmp(cadena2,"opaque"))	// Material opaco
     {
      matpointer[curmat].opaque = 1;
      matpointer[curmat].blend_type=-1;

      token = strtok(NULL,separadores);	 // Ahora leemos si es opaco o transparente
      token2string(token,cadena2);
      if(!strcmp(cadena2,"2sided"))	// Material con 2 caras
      {
       matpointer[curmat].twosided = 1;
      }
      else if(!strcmp(cadena2,"1sided"))	// Material con 2 caras
      {
       matpointer[curmat].twosided = 0;
      }
      else 
      {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. No tiene 1 ni 2 caras\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
      }
     }
     else if(!strcmp(cadena2,"transp")) // Material traslúcido
     {
      matpointer[curmat].opaque=0;

      token = strtok(NULL,separadores);	 // Ahora leemos si es opaco o transparente
      token2string(token,cadena2);
      if(!strcmp(cadena2,"2sided"))	// Material con 2 caras
      {
       matpointer[curmat].twosided = 1;
      }
      else if(!strcmp(cadena2,"1sided"))	// Material con 2 caras
      {
       matpointer[curmat].twosided = 0;
      }
      else
      {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. No tiene 1 ni 2 caras\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
      }

      token = strtok(NULL,separadores);	 // Ahora leemos el tipo de blend
      token2string(token,cadena2);
      if(!strcmp(cadena2,"add"))  	// Blend aditivo
      {
       matpointer[curmat].blend_type=BLEND_ADD;
      }
      else if(!strcmp(cadena2,"blend"))  // Blend normal
      {
       matpointer[curmat].blend_type=BLEND_BLEND;
      }
      else if(!strcmp(cadena2,"multiply"))  // Blend multiplicativo
      {
       matpointer[curmat].blend_type=BLEND_MULTIPLY;
      }
      else if(!strcmp(cadena2,"sub"))  	// Blend sustractivo
      {
       matpointer[curmat].blend_type=BLEND_SUB;      	
      }
      else 
      {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. El blend no es valido\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
      }
     }
     else
     {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. No es opaque ni transp\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
     }       
     // Hasta aquí tenemos el nombre del material, que es estático, su opacidad y el tipo de blend si aplica.
     // Nos falta leer el número de texturas y las texturas

     token = strtok(NULL,separadores);
     token2string(token,cadena2);
     ntextures= atoi(cadena2);

     if(ntextures < 0)
     {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. No puede tener menos de 0 texturas\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
     }
     else if(ntextures == 0)
     {
         matpointer[curmat].textures=NULL;
         matpointer[curmat].multitexblend=NULL;
         matpointer[curmat].texcoordgen=NULL;
     }
     else if(ntextures == 1)
     {
         matpointer[curmat].textures = (int *) malloc (ntextures * sizeof(int));
         matpointer[curmat].multitexblend = (int *) malloc ((ntextures) * sizeof(int));
         matpointer[curmat].texcoordgen = (int *) malloc ((ntextures) * sizeof(int));;
         matpointer[curmat].linearmultiplier = (float *)malloc((ntextures) * sizeof(float));
     }
     else
     {
         matpointer[curmat].textures = (int *) malloc (ntextures * sizeof(int));
         matpointer[curmat].multitexblend = (int *) malloc ((ntextures) * sizeof(int));
         matpointer[curmat].texcoordgen = (int *) malloc ((ntextures) * sizeof(int));
         matpointer[curmat].linearmultiplier = (float *)malloc((ntextures) * sizeof(float));
     }
  
     matpointer[curmat].ntextures = ntextures;

     // Cargamos las texturas
     for(i=0;i<ntextures;i++)
     {
      token = strtok(NULL,separadores);
      token2string(token,cadena2);

      // La carga de la textura la haremos después de conocer si hay cubemap o no!
      
      strcpy(texname,cadena2);
     
      // Carga del tipo de coordenadas de textura
      // En caso de usar shader, aunque se ignoren los tipos de coordenada, lo usamos
      // para saber cuándo una textura es un cubemap...
      token = strtok(NULL,separadores);
      token2string(token,cadena2);

      if((!strcmp(cadena2,"same")) || (!strcmp(cadena2,"uv")))
      {
       matpointer[curmat].texcoordgen[i]=TEXGEN_UV;
      }
      else if(!strcmp(cadena2,"eyelinear"))
      {
       matpointer[curmat].texcoordgen[i]=TEXGEN_EYE_LINEAR;
       if(matpointer[curmat].shader_based == 1 )
       {
        sprintf (FANTASY_DEBUG_STRING, "Warning: el material %s está basado en shader, pero se ha seleccionado texgen tipo eyelinear. Pongo UV\n",matpointer[curmat].matname);
        Debug(DEBUG_LEVEL_ERROR);
        matpointer[curmat].texcoordgen[i]=TEXGEN_UV;
       }
      }
      else if(!strcmp(cadena2,"objectlinear"))
      {
       matpointer[curmat].texcoordgen[i]=TEXGEN_OBJECT_LINEAR;
       if(matpointer[curmat].shader_based == 1 )
       {
        sprintf (FANTASY_DEBUG_STRING, "Warning: el material %s está basado en shader, pero se ha seleccionado texgen tipo objectlinear. Pongo UV\n",matpointer[curmat].matname);
        Debug(DEBUG_LEVEL_ERROR);
        matpointer[curmat].texcoordgen[i]=TEXGEN_UV;
       }
      }
      else if(!strcmp(cadena2,"spheremap"))
      {
       matpointer[curmat].texcoordgen[i]=TEXGEN_SPHERE_MAP;
       if(matpointer[curmat].shader_based == 1 )
       {
        sprintf (FANTASY_DEBUG_STRING, "Warning: el material %s está basado en shader, pero se ha seleccionado texgen tipo spheremap. Pongo UV\n",matpointer[curmat].matname);
        Debug(DEBUG_LEVEL_ERROR);
        matpointer[curmat].texcoordgen[i]=TEXGEN_UV;
       }
      }     	
      else if(!strcmp(cadena2,"cubemap"))
      {
       matpointer[curmat].texcoordgen[i]=TEXGEN_CUBE_MAP;
      }    
      // Ahora podemos cargar la textura
      if(matpointer[curmat].texcoordgen[i] != TEXGEN_CUBE_MAP)
      {
     	matpointer[curmat].textures[i] = ConjuntoTexturas->CargaTextura(texname);
     	        
      }
      else
      {      	
      	matpointer[curmat].textures[i] = ConjuntoTexturas->CargaCubeMap(texname);
      }

      // Si las coordenadas son eyelinear u objectlinear, cogemos el multiplicador
      if((matpointer[curmat].texcoordgen[i]==TEXGEN_OBJECT_LINEAR) ||
      (matpointer[curmat].texcoordgen[i]==TEXGEN_EYE_LINEAR))
      {
       token = strtok(NULL,separadores);
       token2string(token,cadena2);
       matpointer[curmat].linearmultiplier[i]=atof(cadena2);
      }  
      // Finalmente, si no es la primera unidad de textura, vemos qué tipo de blend
      // utiliza esta unidad de textura
      if((i>0) && (matpointer[curmat].shader_based != 1)) // Para tipo shader no se carga
      {
	token = strtok(NULL,separadores);
      	token2string(token,cadena2);

      	if(!strcmp(cadena2,"add"))  	// Blend aditivo
      	{
       	 matpointer[curmat].multitexblend[i]=BLEND_ADD;
      	}
      	else if(!strcmp(cadena2,"modulate"))  // Modulate
      	{
       	 matpointer[curmat].multitexblend[i]=BLEND_MODULATE;
      	}
      	else if(!strcmp(cadena2,"mask"))	// Mask
      	{
	 matpointer[curmat].multitexblend[i]=BLEND_MASK;
      	}
      	else if(!strcmp(cadena2,"mask2"))	// Mask
      	{
      	 matpointer[curmat].multitexblend[i]=BLEND_MASK2;
      	}
      	else if(!strcmp(cadena2,"dot3"))	// Dot3 bump mapping
      	{
	 matpointer[curmat].multitexblend[i]=BLEND_DOT3;
      	}      	
      	else // Por defecto dejamos replace, para darnos cuenta del error
       {     
        sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. Multitex blend no valido\n",matpointer[curmat].matname);
        Debug(DEBUG_LEVEL_ERROR);
        return -1;
       }

      }
      else
        matpointer[curmat].multitexblend[i]=BLEND_MODULATE;
     	
     } // Fin del bucle for

     // Ahora vamos a cargar los parámetros relativos a la iluminación. Ojo, que son opcionales,
     // y pueden ir en cualquier orden!!!
     for(i=0;i<3;i++)
     {
      token = strtok(NULL,separadores);
      if(token == NULL) break;
      token2string(token,cadena2);
      if(!strcmp(cadena2,"specular"))
      {
       	for(j=0;j<3;j++)  // Leemos las 4 componentes
       	{
         token = strtok(NULL,separadores);
         token2string(token,cadena2);
         matpointer[curmat].specular[j]=2.0f*atof(cadena2);
       	}
       	matpointer[curmat].specular[3] = 1.0f;
      }
      else if(!strcmp(cadena2,"emission"))
      {
       	for(j=0;j<3;j++)  // Leemos las 4 componentes
       	{
         token = strtok(NULL,separadores);
         token2string(token,cadena2);
         matpointer[curmat].emission[j]=atof(cadena2);
       	}
       	matpointer[curmat].emission[j] = 1.0f;
      }
      else if((!strcmp(cadena2,"shininess")) || (!strcmp(cadena2,"glossiness")))
      {
         token = strtok(NULL,separadores);
         token2string(token,cadena2);
         matpointer[curmat].shininess=atof(cadena2);
      }
      else 
      {     
       sprintf (FANTASY_DEBUG_STRING, "Material %s no valido. Parámetros de iluminación no válidos\n",matpointer[curmat].matname);
       Debug(DEBUG_LEVEL_ERROR);
       return -1;
      }

     }

     
    }
    curmat++;
   
 }

 materiales = matpointer;
 numero_materiales = nmats;
 pak_close(p);

 if(curmat < nmats)
 {     
   sprintf (FANTASY_DEBUG_STRING, "Fallo al leer el archivo de materiales %s. Hay menos materiales de los definidos en nmats\n",filename);
   Debug(DEBUG_LEVEL_ERROR);
   return -1;
 }
 return nmats;
}