123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- /*
- Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
- Copyright (C) 2009 Id Software, Inc.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
- #include "../doomiphone.h"
- pkHeader_t *pkHeader;
- int pkSize;
- // images and wavs have writable state, so they need separate
- // structs that also point to the source in the pak file
- pkTexture_t *pkTextures;
- pkWav_t *pkWavs;
- void PK_LoadTexture( pkTexture_t *image );
- /*
- ==================
- PK_Init
-
- ==================
- */
- void PK_Init( const char *pakFileName ) {
- printf( "PK_Init( %s )\n", pakFileName );
-
- int fd = open( pakFileName, O_RDONLY );
- if ( fd == -1 ) {
- printf( "Couldn't open file\n" );
- assert( 0 );
- }
- struct stat s;
- fstat( fd, &s );
-
- pkSize = s.st_size;
- pkHeader = mmap( NULL, pkSize, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0 );
-
- // mmap keeps the file internally, we can close our descriptor
- close( fd );
-
- if ( (int)pkHeader == -1 ) {
- printf( "mmap failed: %s\n", strerror( errno ) );
- assert( 0 );
- }
-
- if ( pkHeader->version != PKFILE_VERSION ) {
- printf( "bad pak file version: 0x%x != 0x%x\n", pkHeader->version, PKFILE_VERSION );
- assert( 0 );
- }
-
- // build the local image table
- pkTextures = malloc( sizeof( pkTextures[0] ) * pkHeader->textures.count );
- memset( pkTextures, 0, sizeof( pkTextures[0] ) * pkHeader->textures.count );
- for ( int i = 0 ; i < pkHeader->textures.count ; i++ ) {
- pkTextures[i].textureData = (pkTextureData_t *)( (byte *)pkHeader + pkHeader->textures.tableOfs + i * pkHeader->textures.structSize );
- }
-
- // build the local wav table
- int startLoadingWavs = SysIphoneMicroseconds();
- pkWavs = malloc( sizeof( pkWavs[0] ) * pkHeader->wavs.count );
- memset( pkWavs, 0, sizeof( pkWavs[0] ) * pkHeader->wavs.count );
- for ( int i = 0 ; i < pkHeader->wavs.count ; i++ ) {
- pkWav_t *sfx = &pkWavs[i];
- sfx->wavData = (pkWavData_t *)( (byte *)pkHeader + pkHeader->wavs.tableOfs + i * pkHeader->wavs.structSize );
- // there is no harm in setting the OpenAl static buffer up for everything now
- alGenBuffers( 1, &sfx->alBufferNum );
- int alFormat;
- if ( sfx->wavData->wavChannels == 1 ) {
- if ( sfx->wavData->wavChannelBytes == 1 ) {
- alFormat = AL_FORMAT_MONO8;
- } else {
- alFormat = AL_FORMAT_MONO16;
- }
- } else {
- if ( sfx->wavData->wavChannelBytes == 1 ) {
- alFormat = AL_FORMAT_STEREO8;
- } else {
- alFormat = AL_FORMAT_STEREO16;
- }
- }
- alBufferData( sfx->alBufferNum, alFormat, (byte *)pkHeader + sfx->wavData->wavDataOfs
- , sfx->wavData->wavChannels*sfx->wavData->wavChannelBytes*sfx->wavData->wavNumSamples
- , sfx->wavData->wavRate );
- }
- int endLoadingWavs = SysIphoneMicroseconds();
- printf( "%i usec to load wavs\n", endLoadingWavs - startLoadingWavs );
-
- printf( "Mapped %i bytes of %s at 0x%p\n", pkSize, pakFileName, pkHeader );
- printf( "%4i textures\n", pkHeader->textures.count );
- printf( "%4i wavs\n", pkHeader->wavs.count );
- printf( "%4i raws\n", pkHeader->raws.count );
- #if 0
- // testing
- for ( int j = 0 ; j < 4 ; j++ ) {
- int startTime = Sys_Microseconds();
- int sum = 0;
- for ( int i = 0 ; i < pkSize ; i+=16 ) {
- sum += ((byte *)pkHeader)[i];
- }
- int endTime = Sys_Microseconds();
- printf( "%5.1f mb/s page-in speed (%i)\n", (float)pkSize / (endTime - startTime ), endTime - startTime );
- }
-
- for ( int i = 0 ; i < pkHeader->numTextures ; i++ ) {
- printf( "-------------------------\n" );
- for ( int j = 0 ; j < 8 ; j++ ) {
- pkTexture_t *tex = &pkTextures[i];
- int start = Sys_Microseconds();
- PK_LoadTexture( tex );
- int middle = Sys_Microseconds();
- PK_StretchTexture( tex, 0, 0, 0, 0 );
- int middle2 = Sys_Microseconds();
- PK_StretchTexture( tex, 0, 0, 0, 0 );
- int end = Sys_Microseconds();
- printf( "%i usec load, %i usec first draw, %i usec second draw\n",
- middle - start, middle2 - middle, end - middle2 );
-
- glDeleteTextures( 1, &tex->glTexNum );
- tex->glTexNum = 0;
- }
- }
- #endif
- }
- /*
- ==================
- PK_LoadTexture
-
- ==================
- */
- void PK_LoadTexture( pkTexture_t *tex ) {
- int startTime = SysIphoneMicroseconds();
- const pkTextureData_t *imd = tex->textureData;
- glGenTextures( 1, &tex->glTexNum );
- glBindTexture( GL_TEXTURE_2D, tex->glTexNum );
-
- // load the image directly from the mapped file
- typedef struct {
- int internalFormat;
- int externalFormat;
- int type;
- int bpp;
- } formatInfo_t;
-
- static formatInfo_t formatInfo[9] = {
- { GL_RGB , GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 16 },
- { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, 16 },
- { GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 16 },
- { GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, 32 },
- { GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 16 },
- { GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 0, 0, 4 },
- { GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 0, 0, 4 },
- { GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 0, 0, 2 },
- { GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 0, 0, 2 },
- };
-
- assert( imd->format < 9 );
- formatInfo_t *fi = &formatInfo[imd->format];
-
- unsigned char *s = (byte *)pkHeader + imd->picDataOfs;
- int w = imd->uploadWidth;
- int h = imd->uploadHeight;
- // upload each mip level
- int l = 0;
- int totalSize = 0;
- while( 1 ) {
- int size = (w*h*fi->bpp)/8;
- if ( fi->type == 0 ) {
- if ( size < 32 ) {
- // minimum PVRTC size
- size = 32;
- }
- glCompressedTexImage2D( GL_TEXTURE_2D, l, fi->internalFormat, w, h, 0,
- size, s );
- } else {
- glTexImage2D( GL_TEXTURE_2D, l, fi->internalFormat, w, h, 0,
- fi->externalFormat, fi->type, s );
- }
- GLCheckError( "texture upload" );
- totalSize += size;
- if ( ++l == imd->numLevels ) {
- break;
- }
- if ( w == 1 && h == 1 ) {
- break;
- }
- s += size;
- w >>= 1;
- if ( w == 0 ) {
- w = 1;
- }
- h >>= 1;
- if ( h == 0 ) {
- h = 1;
- }
- }
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, imd->minFilter );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, imd->magFilter );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, imd->wrapS );
- glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, imd->wrapT );
- glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2.0f );
-
- int endTime = SysIphoneMicroseconds();
-
- printf( "%5.1f mb/s TexImage for %s\n", (float)totalSize /
- ( endTime - startTime ), imd->name.name );
- }
- /*
- ==================
- PK_FindTexture
-
- Fully creates the gl texture before returning.
- ==================
- */
- pkTexture_t *PK_FindTexture( const char *imageName ) {
- int index;
- pkTexture_t *texData = (pkTexture_t *)PK_FindType( imageName, &pkHeader->textures, &index );
- if ( !texData ) {
- return NULL;
- }
- pkTexture_t *tex = pkTextures + index;
- if ( tex->glTexNum == 0 ) {
- PK_LoadTexture( tex );
- }
- return tex;
- }
- /*
- ==================
- PK_FindWav
-
- ==================
- */
- pkWav_t *PK_FindWav( const char *soundName ) {
- int index;
- pkWavData_t *wavData = (pkWavData_t *)PK_FindType( soundName, &pkHeader->wavs, &index );
- if ( !wavData ) {
- return NULL;
- }
- pkWav_t *wav = pkWavs + index;
-
- // create the OpenAL buffer
-
- return wav;
- }
- /*
- ==================
- PK_FindRaw
-
- ==================
- */
- const byte *PK_FindRaw( const char *rawName, int *len ) {
- pkRawData_t *raw = (pkRawData_t *)PK_FindType( rawName, &pkHeader->raws, NULL );
- if ( !raw ) {
- if ( len ) {
- *len = -1;
- }
- return NULL;
- }
-
- if ( len ) {
- *len = raw->rawDataLen;
- }
- return (byte *)pkHeader + raw->rawDataOfs;
- }
- /*
- ==================
- PK_HashName
-
- ==================
- */
- int PK_HashName( const char *name, char canonical[MAX_PK_NAME] ) {
- int o = 0;
- int hash = 0;
-
- do {
- int c = name[o];
- if ( c == 0 ) {
- break;
- }
- // backslashes to forward slashes
- if ( c == '\\' ) {
- c = '/';
- }
- // to lowercase
- c = tolower( c );
- canonical[o++] = c;
- hash = (hash << 5) - hash + c;
- } while ( o < MAX_PK_NAME-1 );
- canonical[o] = 0;
-
- return hash;
- }
- /*
- ==================
- PK_FindType
-
- ==================
- */
- const pkName_t *PK_FindType( const char *rawName, const pkType_t *type, int *indexOutput ) {
- char canonicalName[MAX_PK_NAME];
-
- int hash = PK_HashName( rawName, canonicalName );
-
- int hashChain = hash & (PK_HASH_CHAINS-1);
-
- int index = type->hashChains[hashChain];
- while ( index != -1 ) {
- assert( index >= 0 && index < type->count );
- const pkName_t *name = (pkName_t *)((byte *)pkHeader + type->tableOfs + index * type->structSize );
- if ( name->nameHash == hash && !strcmp( canonicalName, name->name ) ) {
- // this is it
- if ( indexOutput ) {
- *indexOutput = index;
- }
- return name;
- }
- index = name->nextOnHashChain;
- }
-
- // not found
- if ( indexOutput ) {
- *indexOutput = -1;
- }
- return NULL;
- }
- /*
- ==================
- PK_BindTexture
-
- ==================
- */
- void PK_BindTexture( pkTexture_t *tex ) {
- assert( tex->glTexNum );
- glBindTexture( GL_TEXTURE_2D, tex->glTexNum );
- }
- /*
- ==================
- PK_DrawTexture
-
- ==================
- */
- void PK_DrawTexture( pkTexture_t *tex, int x, int y ) {
- PK_BindTexture( tex );
- int w = tex->textureData->srcWidth;
- int h = tex->textureData->srcHeight;
-
- glBegin( GL_QUADS );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex2i( x, y );
- glTexCoord2f( tex->textureData->maxS, 0.0f ); glVertex2i( x+w, y );
- glTexCoord2f( tex->textureData->maxS, tex->textureData->maxT ); glVertex2i( x+w, y+h );
- glTexCoord2f( 0.0f, tex->textureData->maxT ); glVertex2i( x, y+h );
-
- glEnd();
- }
- void PK_StretchTexture( pkTexture_t *tex, float x, float y, float w, float h ) {
- PK_BindTexture( tex );
-
- glBegin( GL_QUADS );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex2i( x, y );
- glTexCoord2f( tex->textureData->maxS, 0.0f ); glVertex2i( x+w, y );
- glTexCoord2f( tex->textureData->maxS, tex->textureData->maxT ); glVertex2i( x+w, y+h );
- glTexCoord2f( 0.0f, tex->textureData->maxT ); glVertex2i( x, y+h );
-
- glEnd();
- }
|