/* Load a texture from a 2D image */ void glTexImage2D(GLenum target, GLint level, GLint internal_fmt, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { pvr_ptr_t txr; assert_msg(border == 0 && level == 0, "Borders and levels not supported."); assert_msg((internal_fmt & ~1) == (format & ~1), "Pixel conversion not supported."); /* Allocate space for it */ txr = pvr_mem_malloc(width * height * 2); /* Load the texture data */ if ((internal_fmt & 1) != (format & 1)) pvr_txr_load_ex((GLvoid *)pixels, txr, width, height, PVR_TXRLOAD_16BPP); else pvr_txr_load((GLvoid *)pixels, txr, width * height * 2); /* Store texture state in context */ gl_cur_texture->txr.width = width; gl_cur_texture->txr.height = height; gl_cur_texture->txr.format = internal_fmt; gl_cur_texture->txr.base = txr; gl_pbuf_submitted = GL_FALSE; }
static pvr_ptr_t load_bumpmap (const char *filename) { void *data = malloc (128 * 128 * 2); pvr_ptr_t pvraddr; FILE *fp = fopen (filename, "rb"); if (!fp) { printf ("Couldn't load bump map '%s'\n", filename); exit (1); } fread (data, 1, 128 * 128 * 2, fp); fclose (fp); pvraddr = pvr_mem_malloc (128 * 128 * 2); pvr_txr_load (data, pvraddr, 128 * 128 * 2); free (data); return pvraddr; }
void Load_Texture(const char* fn, Texture* t){ FILE* fp; header_t hdr; fp = fopen(fn,"r"); fread(&hdr,sizeof(hdr),1,fp); // read in the header t->w = hdr.width; t->h = hdr.height; t->fmt = hdr.type; //Allocate texture memory t->txt = pvr_mem_malloc(hdr.size); //Temporary ram storage of texture void* temp = malloc(hdr.size); // Load texture into ram fread(temp,hdr.size,1,fp); // SQ copy into VRAM pvr_txr_load(temp,t->txt,hdr.size); //Free RAM free(temp); temp = NULL; fclose(fp); /* Palette loading and management */ if( ((t->fmt >> 27) & 7) > 4 ) { if(t->fmt & PVR_TXRFMT_PAL4BPP){ // Append palette suffix to filepath char pf[64]; strcpy(pf,fn); strcat(pf,".pal"); fp = fopen(pf,"r"); pal_header_t phdr; //read in the 8-byte header fread(&phdr,sizeof(pal_header_t),1,fp); //setup buffer void *palette = malloc(phdr.numcolors*4); Uint32 i; //Make entries readable to PVR Uint32* packed = (Uint32*)palette; //Load entries in to buffer fread(packed,phdr.numcolors*4,1,fp); //Load palette entries into correct location ( first 512 bank) for(i = Pindex4*16; i < (Pindex4*16) + phdr.numcolors*4;i++){ pvr_set_pal_entry(i,packed[i]); } //Set palette # t->palette = Pindex4; t->fmt |= PVR_TXRFMT_4BPP_PAL(Pindex4); //Increase palettte index to prevent overwrite Pindex4++; //32 possible palettes in 512 bank if(Pindex4 == 32){ Pindex4 = 0; // overwrite } packed = NULL; free(palette); fclose(fp); } else if(t->fmt & PVR_TXRFMT_PAL8BPP){ char pf[64]; strcpy(pf,fn); strcat(pf,".pal"); fp = fopen(pf,"r"); pal_header_t phdr; fread(&phdr,sizeof(pal_header_t),1,fp); void * palette = malloc(phdr.numcolors*4); Uint32 i; Uint32* packed = (Uint32*)palette; fread(packed,phdr.numcolors*4,1,fp); //Load palette entries into the second 512 bank for(i = (512 + Pindex8*256); i < (Pindex8*256 + 512) + phdr.numcolors*4;i++){ pvr_set_pal_entry(i,packed[i]); } t->palette = Pindex8 | 0x80; t->fmt |= PVR_TXRFMT_8BPP_PAL(Pindex8+2); Pindex8++; //Only 2 8-bit palettes can fit into second 512 bank if(Pindex8 == 2){ Pindex8 = 0; } packed = NULL; free(palette); fclose(fp); } } }
/* Open the pvr texture and send it to VRAM, then bind it to the glKosTex2D context */ void loadpvr( const char * file_name, GLuint *txr ) { /* set up the files and buffers */ FILE * pvr_file; char * pvr_header, * pvr_buffer; int header_len; struct pvr_tex pvr; /* open the pvr file */ pvr_file = fopen( file_name ,"rb"); if (pvr_file==NULL) printf ("File error",stderr); /* Read the possible 0x00100000 byte header */ pvr_header = (char*)malloc( 32 ); fread( pvr_header, 16, 2, pvr_file); /* obtain the PVR file size using fseek */ fseek (pvr_file , 0 , SEEK_END); int pvrSize = ftell (pvr_file); /* Move to the begining of the PVR file */ fseek (pvr_file , 0, SEEK_SET); /* Allocate RAM to contain the PVR file */ if( pvr_buffer ) free( pvr_buffer ); pvr_buffer = (char*)memalign( 32, pvrSize ); //pvr_buffer = (char*)malloc( pvrSize ); if ( pvr_buffer == NULL ) printf ("Memory error\n"); /* GBIX = 0x00100000 byte header */ if( (char)pvr_header[0] == 'G' && (char)pvr_header[1] == 'B' && (char)pvr_header[2] == 'I' && (char)pvr_header[3] == 'X' ) header_len = 32; /* PVRT = 0x00010000 byte header */ else if ( (char)pvr_header[0] == 'P' && (char)pvr_header[1] == 'V' && (char)pvr_header[2] == 'R' ) header_len = 16; /* Move past the header */ fseek (pvr_file , header_len, SEEK_SET); /* Read the pvr texture data into RAM and close the file */ fread (pvr_buffer,16,(pvrSize-header_len)/16,pvr_file); fclose( pvr_file ); /* Get PVR Colorspace */ unsigned int pvr_color = (unsigned int)pvr_header[header_len-8]; switch( pvr_color ) { case 0x00: pvr.txrColor = PVR_TXRFMT_ARGB1555; break; //(bilevel translucent alpha 0,255) case 0x01: pvr.txrColor = PVR_TXRFMT_RGB565; break; //(non translucent RGB565 ) case 0x02: pvr.txrColor = PVR_TXRFMT_ARGB4444; break; //(translucent alpha 0-255) case 0x03: pvr.txrColor = PVR_TXRFMT_YUV422; break; //(non translucent UYVY ) case 0x04: pvr.txrColor = PVR_TXRFMT_BUMP; break; //(special bump-mapping format) case 0x05: pvr.txrColor = PVR_TXRFMT_PAL4BPP; break; //(4-bit palleted texture) case 0x06: pvr.txrColor = PVR_TXRFMT_PAL8BPP; break; //(8-bit palleted texture) default: break; } /* Get PVR Format. Mip-Maps and Palleted Textures not Currently handled */ unsigned int pvr_fmt = (unsigned int)pvr_header[header_len-7]; switch( pvr_fmt ) { case 0x01: pvr.txrFmt = PVR_TXRFMT_TWIDDLED; break;//SQUARE TWIDDLED //case 0x02: pvr.txrFmt = SQUARE TWIDDLED & MIPMAP case 0x03: pvr.txrFmt = PVR_TXRFMT_VQ_ENABLE | PVR_TXRFMT_TWIDDLED; break;//VQ TWIDDLED //case 0x04: pvr.txrFmt = VQ & MIPMAP //case 0X05: pvr.txrFmt = 8-BIT CLUT TWIDDLED //case 0X06: pvr.txrFmt = 4-BIT CLUT TWIDDLED //case 0x07: pvr.txrFmt = 8-BIT DIRECT TWIDDLED //case 0X08: pvr.txrFmt = 4-BIT DIRECT TWIDDLED case 0x09: pvr.txrFmt = PVR_TXRFMT_NONTWIDDLED; break;//RECTANGLE case 0x0B: pvr.txrFmt = PVR_TXRFMT_STRIDE | PVR_TXRFMT_NONTWIDDLED; break;//RECTANGULAR STRIDE case 0x0D: pvr.txrFmt = PVR_TXRFMT_TWIDDLED; break;//RECTANGULAR TWIDDLED case 0x10: pvr.txrFmt = PVR_TXRFMT_VQ_ENABLE | PVR_TXRFMT_NONTWIDDLED; break;//SMALL VQ //case 0x11: pvr.txrFmt = SMALL VQ & MIPMAP //case 0x12: pvr.txrFmt = SQUARE TWIDDLED & MIPMAP default: pvr.txrFmt = PVR_TXRFMT_NONE; break; } /* Get PVR Texture Width */ if( (unsigned int)pvr_header[header_len-4] == 0x08 && (unsigned int)pvr_header[header_len-3] == 0x00 ) pvr.texWidth = 8; else if( (unsigned int)pvr_header[header_len-4] == 0x10 && (unsigned int)pvr_header[header_len-3] == 0x00 ) pvr.texWidth = 16; else if( (unsigned int)pvr_header[header_len-4] == 0x20 && (unsigned int)pvr_header[header_len-3] == 0x00 ) pvr.texWidth = 32; else if( (unsigned int)pvr_header[header_len-4] == 0x40 && (unsigned int)pvr_header[header_len-3] == 0x00 ) pvr.texWidth = 64; else if( (unsigned int)pvr_header[header_len-4] == -0x80 && (unsigned int)pvr_header[header_len-3] == 0x00 ) pvr.texWidth = 128; else if( (unsigned int)pvr_header[header_len-4] == 0x00 && (unsigned int)pvr_header[header_len-3] == 0x01 ) pvr.texWidth = 256; else if( (unsigned int)pvr_header[header_len-4] == 0x00 && (unsigned int)pvr_header[header_len-3] == 0x02 ) pvr.texWidth = 512; else if( (unsigned int)pvr_header[header_len-4] == 0x00 && (unsigned int)pvr_header[header_len-3] == 0x04 ) pvr.texWidth = 1024; /* Get PVR Texture Height */ if( (unsigned int)pvr_header[header_len-2] == 0x08 && (unsigned int)pvr_header[header_len-1] == 0x00 ) pvr.texHeight = 8; else if( (unsigned int)pvr_header[header_len-2] == 0x10 && (unsigned int)pvr_header[header_len-1] == 0x00 ) pvr.texHeight = 16; else if( (unsigned int)pvr_header[header_len-2] == 0x20 && (unsigned int)pvr_header[header_len-1] == 0x00 ) pvr.texHeight = 32; else if( (unsigned int)pvr_header[header_len-2] == 0x40 && (unsigned int)pvr_header[header_len-1] == 0x00 ) pvr.texHeight = 64; else if( (unsigned int)pvr_header[header_len-2] == -0x80 && (unsigned int)pvr_header[header_len-1] == 0x00 ) pvr.texHeight = 128; else if( (unsigned int)pvr_header[header_len-2] == 0x00 && (unsigned int)pvr_header[header_len-1] == 0x01 ) pvr.texHeight = 256; else if( (unsigned int)pvr_header[header_len-2] == 0x00 && (unsigned int)pvr_header[header_len-1] == 0x02 ) pvr.texHeight = 512; else if( (unsigned int)pvr_header[header_len-2] == 0x00 && (unsigned int)pvr_header[header_len-1] == 0x04 ) pvr.texHeight = 1024; printf("PVR TXR Size: %i bytes, %ix%i pixels\n", pvrSize, pvr.texWidth, pvr.texHeight ); /* Allocate VRAM */ if(pvr.txrAddr) pvr_mem_free(pvr.txrAddr); pvr.txrAddr = pvr_mem_malloc(pvrSize); /* Transfer the texture from RAM to VRAM */ /* SH4->PVR DMA Transfer */ if( header_len != 16 ) { if( pvrSize > 16384) dcache_flush_range((uint32)pvr_buffer, 16384); else dcache_flush_range((uint32)pvr_buffer, pvrSize); while (!pvr_dma_ready()); pvr_dma_transfer( (void*)pvr_buffer, (uint32)pvr.txrAddr, pvrSize, PVR_DMA_VRAM64, PVR_TXRLOAD_NONBLOCK, NULL, 0); } /* SH4->PVR SQ Transfer */ else { pvr_txr_load( pvr_buffer, pvr.txrAddr, pvrSize); } /* Free the RAM */ if( pvr_header ) free( pvr_header ); if( pvr_buffer ) free( pvr_buffer ); /* Bind the texture data to the glTex2D context */ glKosTex2D( pvr.txrColor | pvr.txrFmt, pvr.texWidth, pvr.texHeight, pvr.txrAddr); }