mirror of
https://github.com/id-Software/DOOM-iOS.git
synced 2026-03-20 00:49:34 +01:00
Source release for DOOM Classic for iOS version 2.1
This commit is contained in:
398
code/iphone/.svn/text-base/ipak.c.svn-base
Normal file
398
code/iphone/.svn/text-base/ipak.c.svn-base
Normal file
@@ -0,0 +1,398 @@
|
||||
/*
|
||||
* ipak.c
|
||||
* doom
|
||||
*
|
||||
* Created by John Carmack on 4/9/09.
|
||||
* Copyright 2009 __MyCompanyName__. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
alBufferData( sfx->alBufferNum, alFormat, (byte *)pkHeader + sfx->wavData->wavDataOfs
|
||||
, sfx->wavData->wavChannels*sfx->wavData->wavChannelBytes*sfx->wavData->wavNumSamples
|
||||
, sfx->wavData->wavRate );
|
||||
#else
|
||||
// This should just store out a pointer, so the data won't get touched until it is actually
|
||||
// used to play a sound.
|
||||
extern void alBufferDataStatic(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq);
|
||||
|
||||
alBufferDataStatic( sfx->alBufferNum, alFormat, (byte *)pkHeader + sfx->wavData->wavDataOfs
|
||||
, sfx->wavData->wavChannels*sfx->wavData->wavChannelBytes*sfx->wavData->wavNumSamples
|
||||
, sfx->wavData->wavRate );
|
||||
#endif
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user