// read palette files into buffer --------------------------------------------- // PRIVATE void ReadPalettes() { // exit if nothing to read if ( NumLoadedPalettes == 0 ) PANIC( "no palette defined." ); if ( ( PaletteMem = (char *) ALLOCMEM( PALETTE_SIZE * NumLoadedPalettes ) ) == NULL ) OUTOFMEM( no_palette_mem ); if ( display_info ) { MSGPUT( "Loading palettes" ); if ( show_palettes_loaded ) { MSGOUT( ":\n" ); } else { MSGPUT( "..." ); } } // load all palettes size_t readofs = 0; for ( int pid = 0; pid < NumLoadedPalettes; pid++ ) { if ( display_info && !show_palettes_loaded ) MSGPUT( "." ); FILE *fp = SYS_fopen( palette_fnames[ pid ], "rb" ); if ( fp == NULL ) FERROR( palette_not_found, palette_fnames[ pid ] ); if ( display_info && show_palettes_loaded ) { MSGOUT( "loading \"%s\" (palette)\n", palette_fnames[ pid ] ); } size_t bytesread = SYS_fread( PaletteMem + readofs, 1, PALETTE_SIZE, fp ); if ( bytesread != PALETTE_SIZE ) FERROR( palette_readerror, palette_fnames[ pid ] ); readofs += PALETTE_SIZE; SYS_fclose( fp ); } if ( display_info ) { MSGOUT( "done.\n" ); } }
// read binary demo file as one huge block ------------------------------------ // PRIVATE int DEMO_BinaryReadDemo( FILE *fp, int infomsgs, int errormsgs ) { ASSERT( fp != NULL ); ASSERT( demo_data == NULL ); // get file size if ( SYS_fseek( fp, 0, SEEK_END ) != 0 ) { return FALSE; } size_t demosize = SYS_ftell( fp ); if ( SYS_fseek( fp, 0, SEEK_SET ) != 0 ) { return FALSE; } // check for demo header and parse it if present size_t headersize = DEMO_ParseDemoHeader( fp, -1, infomsgs ); if ( demosize >= headersize ) { demosize -= headersize; } if ( demosize == 0 ) { return FALSE; } // allocate mem for demo data demo_data = (char *) ALLOCMEM( demosize ); if ( demo_data == NULL ) { if ( errormsgs ) CON_AddLine( "no mem for demo replay." ); return FALSE; } // read entire file into single memory block if ( SYS_fread( demo_data, 1, demosize, fp ) != demosize ) { if ( errormsgs ) CON_AddLine( "error reading demo file." ); return FALSE; } return TRUE; }
// play specified stream file ------------------------------------------------- // int AUDs_PlayAudioStream( char *fname ) { if (SoundDisabled) return 1; ASSERT(fname!=NULL); if (Mix_PlayingMusic()) Mix_HaltMusic(); if (music != NULL) { Mix_FreeMusic(music); FREEMEM(tmp_music_buffer); tmp_music_buffer = NULL; music = NULL; } // because SDL_RWFromFP doesn't work cross platform, we need // to get a little bit kinky // set up a buffer for the file size_t tmp_music_size = 0; // get the size of this sample tmp_music_size = SYS_GetFileLength(fname); if (tmp_music_size <= 0) { return 1; // return on error } // alloc space for the buffer if (tmp_music_buffer != NULL) { printf("ERROR: Shouldn't be this far without being cleaned up previously\n"); FREEMEM(tmp_music_buffer); tmp_music_buffer = NULL; } tmp_music_buffer = (char *)ALLOCMEM(tmp_music_size + 1); // open the sample file FILE *musicfp = SYS_fopen(fname, "rb"); if (musicfp == NULL) return 1; // read the file into the temp_sample_buffer int read_rc = SYS_fread((void *)tmp_music_buffer, 1, tmp_music_size, musicfp); if(read_rc <= 0) { MSGOUT("ERROR: Error reading music %s.", fname); return FALSE; } SDL_RWops *musicrwops = SDL_RWFromMem((void *)tmp_music_buffer, tmp_music_size); music = Mix_LoadMUS_RW(musicrwops, 1); //MSGOUT(" PlayAudioStream() with %s ", fname); if (music == NULL) { printf("Mix_LoadMUS(\"%s\"): %s\n", fname, Mix_GetError()); // this might be a critical error... FREEMEM(tmp_music_buffer); tmp_music_buffer = NULL; return 1; } Mix_VolumeMusic(128); if (music != NULL) { Mix_PlayMusic(music, 0); } //Pick up your your toys when you finish SYS_fclose(musicfp); return 1; }
int AUDs_LoadWaveFile( int num ) { if (SoundDisabled) return AUD_RETURN_SUCCESS; ASSERT( ( num >= 0 ) && ( num < MAX_SAMPLES ) ); if ( !SoundAvailable ) return AUD_RETURN_SUCCESS; // read the sample and assign the list entry sample_s* pSample = SND_ReadSample( &SampleInfo[ num ] ); SND_ConvertRate( pSample, aud_sample_quality ); // because SDL_RWFromFP doesn't work cross platform, we need // to get a little bit kinky // set up a buffer for the file char *tmp_sample_buffer = NULL; size_t tmp_sample_size = 0; // get the size of this sample tmp_sample_size = SYS_GetFileLength(SampleInfo[num].file); if (tmp_sample_size <= 0) { return FALSE; // return on error } // alloc space for the buffer tmp_sample_buffer = (char *)ALLOCMEM(tmp_sample_size + 1); // open the sample file FILE *wave = SYS_fopen(SampleInfo[num].file, "rb"); if (wave == NULL) return FALSE; // read the file into the temp_sample_buffer int read_rc = SYS_fread((void *)tmp_sample_buffer, 1, tmp_sample_size, wave); if (read_rc <= 0) { MSGOUT("ERROR: Error reading sample %s.", SampleInfo[num].file); return FALSE; } SDL_RWops *waverwops = SDL_RWFromMem((void *)tmp_sample_buffer, tmp_sample_size); snd_chunks[num] = Mix_LoadWAV_RW(waverwops, 0); SYS_fclose(wave); FREEMEM( tmp_sample_buffer ); FREEMEM( pSample->samplebuffer ); pSample->samplebuffer = NULL; #ifdef SHOW_SAMPLE_LOADING_INFO MSGOUT("loaded %-12s to slot %03d: rate: %05d, numch: %02d, type: %s, bytes: %07d", SampleInfo[ num ].file, num, pSample->samplerate, pSample->numchannels, ( pSample->samplesize == 8 ) ? "8" : "16" , pSample->samplebytes ); #endif // SHOW_SAMPLE_LOADING_INFO // store the slot submitted to the play functions SampleInfo[ num ].samplepointer = (char *)num; //CAVEAT: for now we store the number of refframes in size SampleInfo[ num ].size = FLOAT2INT( (float) FRAME_MEASURE_TIMEBASE * (float) pSample->samplebytes / (float) ( pSample->samplerate * pSample->alignment ) + 0.5f ); FREEMEM( pSample ); return AUD_RETURN_SUCCESS; }
// read needed textures into memory ------------------------------------------- // PRIVATE void ReadTextures() { // exit if nothing to read if ( NumLoadedTextures == 0 ) return; if ( display_info ) { MSGPUT( "Loading textures" ); if ( show_textures_loaded ) { MSGOUT( ":\n" ); } else { MSGPUT( "..." ); } } // get filesizes of textures to allocate mem in one piece size_t texmemsize = 0; int tid = 0; for ( tid = 0; tid < NumLoadedTextures; tid++ ) { ssize_t siz = SYS_GetFileLength( TextureInfo[ tid ].file ); if ( siz == -1 ) FERROR( texture_not_found, TextureInfo[ tid ].file ); texmemsize += siz; } // allocate texture buffer TextureMem = (char *) ALLOCMEM( texmemsize + sizeof( TextureMap ) * NumLoadedTextures ); if ( TextureMem == NULL ) OUTOFMEM( no_texture_mem ); char *texreadpo = TextureMem + sizeof( TextureMap ) * NumLoadedTextures; TextureMap *controlpo = (TextureMap *) TextureMem; size_t stillfree = texmemsize; // read in texturedata and fill control structures for ( tid = 0; tid < NumLoadedTextures; tid++ ) { if ( ( ( tid & 0x03 ) == 0 ) && display_info && !show_textures_loaded ) MSGPUT( "." ); FILE *fp = SYS_fopen( TextureInfo[ tid ].file, "rb" ); if ( fp == NULL ) FERROR( texture_not_found, TextureInfo[ tid ].file ); if ( display_info && show_textures_loaded ) { MSGOUT( "loading \"%s\" (texture)\n", TextureInfo[ tid ].file ); } size_t bytesread = SYS_fread( texreadpo, 1, stillfree, fp ); if ( bytesread == 0 ) FERROR( texture_readerror, TextureInfo[ tid ].file ); // if geometry not explicitly specified read it from header if ( ( TextureInfo[ tid ].width == -1 ) || ( TextureInfo[ tid ].height == -1 ) ) { TexHeader *header = (TexHeader *) texreadpo; // swap endianness of TexHeader SYS_SwapTexHeader( header ); if ( stricmp( header->signature, TEX_SIGNATURE ) != 0 ) PERROR( tex_sig_invalid ); if ( header->version < REQUIRED_TEX_VERSION ) PERROR( tex_ver_invalid ); TextureInfo[ tid ].width = header->width; TextureInfo[ tid ].height = header->height; stillfree -= sizeof( TexHeader ); bytesread -= sizeof( TexHeader ); texreadpo += sizeof( TexHeader ); } // set additional texture info fields TextureInfo[ tid ].flags = TEXINFOFLAG_NONE; // fill texture control structure ----------------------------------- controlpo->Width = CeilPow2Exp( TextureInfo[ tid ].width ); controlpo->Height = CeilPow2Exp( TextureInfo[ tid ].height ); // check validity of texture geometry if ( ( controlpo->Width < TEX_WIDTH_POW2_MIN ) || ( controlpo->Width > TEX_WIDTH_POW2_MAX ) || ( controlpo->Height < TEX_HEIGHT_POW2_MIN ) || ( controlpo->Height > TEX_HEIGHT_POW2_MAX ) || ( controlpo->Width < controlpo->Height ) || // check texture's aspect ratio ( ( controlpo->Width - controlpo->Height ) > 1 ) ) { SYS_fclose( fp ); PERROR( "texture dimension not allowed (texture %d).", tid + 1 ); } // calculate geometry code used by texture mapper dword geom = ( controlpo->Width - TEX_WIDTH_POW2_MIN ) * 2; if ( controlpo->Width == controlpo->Height ) geom++; controlpo->Geometry = geom - 1; // set pointers to texture bitmap and name controlpo->BitMap = texreadpo; controlpo->TexMapName = TextureInfo[ tid ].name; // set additional texture fields controlpo->Flags = TEXFLG_NONE; controlpo->LOD_small = 0; controlpo->LOD_large = 0; controlpo->TexPalette = NULL; controlpo->TexelFormat = TEXFMT_STANDARD; // store pointer to texture in texture info table TextureInfo[ tid ].texpointer = controlpo; TextureInfo[ tid ].standardbitmap = controlpo->BitMap; stillfree -= bytesread; texreadpo += bytesread; controlpo++; SYS_fclose( fp ); } if ( display_info ) { MSGOUT( "done.\n" ); } }
// read bitmaps and charsets into memory -------------------------------------- // PRIVATE void ReadBitmapsAndCharsets() { // exit if nothing to read if ( ( NumLoadedBitmaps == 0 ) && ( NumLoadedCharsets == 0 ) ) return; // print message if ( display_info ) { MSGPUT( "Loading bitmaps and charsets" ); if ( show_bitmaps_loaded ) { MSGOUT( ":\n" ); } else { MSGPUT( "..." ); } } // get filesizes of bitmap files size_t bitmmemsize = 0; int bmid = 0; for ( bmid = 0; bmid < NumLoadedBitmaps; bmid++ ) { ssize_t siz = SYS_GetFileLength( BitmapInfo[ bmid ].file ); if ( siz == -1 ) FERROR( bitmap_not_found, BitmapInfo[ bmid ].file ); bitmmemsize += siz; } // get filesizes of charset files int ftid = 0; for ( ftid = 0; ftid < NumLoadedCharsets; ftid++ ) { ssize_t siz; // if geometry not set interpret specified file as info-file if ( CharsetInfo[ ftid ].width == -1 ) { siz = SYS_GetFileLength( CharsetInfo[ ftid ].file ); if ( siz == -1 ) FERROR( fontinfo_not_found, CharsetInfo[ ftid ].file ); CopyFileNameAlterExt( paste_str, CharsetInfo[ ftid ].file, FONT_EXTENSION ); ssize_t gsiz = SYS_GetFileLength( paste_str ); if ( gsiz == -1 ) FERROR( font_not_found, paste_str ); siz += gsiz; } else { siz = SYS_GetFileLength( CharsetInfo[ ftid ].file ); if ( siz == -1 ) FERROR( font_not_found, CharsetInfo[ ftid ].file ); } bitmmemsize += siz; } // allocate buffer for bitmaps and charsets if ( ( BitmapMem = (char *) ALLOCMEM( bitmmemsize ) ) == NULL ) OUTOFMEM( no_bitmap_mem ); char *bitmreadpo = BitmapMem; size_t stillfree = bitmmemsize; // read in raw bitmap files ----------------------------------------------- for ( bmid = 0; bmid < NumLoadedBitmaps; bmid++ ) { if ( ( ( bmid & 0x03 ) == 0 ) && display_info && !show_bitmaps_loaded ) MSGPUT( "." ); FILE *fp = SYS_fopen( BitmapInfo[ bmid ].file, "rb" ); if ( fp == NULL ) FERROR( bitmap_not_found, BitmapInfo[ bmid ].file ); if ( display_info && show_bitmaps_loaded ) MSGOUT( "loading \"%s\" (bitmap)\n", BitmapInfo[ bmid ].file ); ssize_t bytesread = SYS_fread( bitmreadpo, 1, stillfree, fp ); if ( bytesread == 0 ) FERROR( bitmap_readerror, BitmapInfo[ bmid ].file ); // if width and height not already set header must be present if ( BitmapInfo[ bmid ].width == -1 ) { BdtHeader *header = (BdtHeader *) bitmreadpo; // swap endianness of BdtHeader SYS_SwapBdtHeader( header ); if ( stricmp( header->signature, BDT_SIGNATURE ) != 0 ) PERROR( bdt_sig_invalid ); if ( header->version < REQUIRED_BDT_VERSION ) PERROR( bdt_ver_invalid ); // store width and height BitmapInfo[ bmid ].width = header->width; BitmapInfo[ bmid ].height = header->height; // store pointer to bitmap into control structure (header excluded) BitmapInfo[ bmid ].bitmappointer = (char *) ( header + 1 ); } else { // store pointer to bitmap into control structure (was raw format) BitmapInfo[ bmid ].bitmappointer = bitmreadpo; } // store pointer to originally loaded data (needed for different color depths) BitmapInfo[ bmid ].loadeddata = BitmapInfo[ bmid ].bitmappointer; // set bitmap name (static storage!) ASSERT( num_default_bitmaps == BM_CONTROLFILE_NUMBER ); ASSERT( bmid < num_default_bitmaps ); BitmapInfo[ bmid ].name = (char *) default_bitmap_names[ bmid ]; stillfree -= bytesread; bitmreadpo += bytesread; SYS_fclose( fp ); } // read in raw charset data ----------------------------------------------- int charset_datasize = 0; for ( ftid = 0; ftid < NumLoadedCharsets; ftid++ ) { if ( ( ( ftid & 0x03 ) == 0 ) && display_info && !show_bitmaps_loaded ) MSGPUT( "." ); if ( CharsetInfo[ ftid ].srcwidth == -1 ) { FILE *fp = SYS_fopen( CharsetInfo[ ftid ].file, "rb" ); if ( fp == NULL ) FERROR( fontinfo_not_found, CharsetInfo[ ftid ].file ); if ( display_info && show_bitmaps_loaded ) MSGOUT( "loading \"%s\" (fontinfo)\n", CharsetInfo[ ftid ].file ); size_t gsiz = SYS_fread( bitmreadpo, 1, stillfree, fp ); if ( gsiz < sizeof( PfgHeader ) + 8 ) FERROR( fontinfo_readerror, CharsetInfo[ ftid ].file ); PfgHeader *header = (PfgHeader *) bitmreadpo; // swap endianness of PfgHeader SYS_SwapPfgHeader( header ); if ( stricmp( header->signature, PFG_SIGNATURE ) != 0 ) PERROR( pfg_sig_invalid ); if ( header->version < REQUIRED_PFG_VERSION ) PERROR( pfg_ver_invalid ); CharsetInfo[ ftid ].srcwidth = header->srcwidth; CharsetInfo[ ftid ].width = header->width; CharsetInfo[ ftid ].height = header->height; // ensure table is multiple of four in length size_t geomsiz = gsiz - sizeof( PfgHeader ) - 4; if ( ( geomsiz & 0x03 ) != 0x00 ) FERROR( pfg_corrupted, CharsetInfo[ ftid ].file ); // create pointer to table excluding startchar dword *geomtab = (dword *)( bitmreadpo + sizeof( PfgHeader ) + 4 ); //TODO: //CAVEAT: //NOTE: // the font-type determination assumes that exactly // those fonts with width==height are fixed-size fonts. // determine whether fixed-size font int fonttype = ( header->width == header->height ); // swap endianness of geometry table SYS_SwapPfgTable( fonttype, geomtab, geomsiz ); // geometry pointer must point one dword past the geometry table!! CharsetInfo[ ftid ].geompointer = geomtab; bitmreadpo += gsiz; stillfree -= gsiz; SYS_fclose( fp ); CopyFileNameAlterExt( paste_str, CharsetInfo[ ftid ].file, FONT_EXTENSION ); if ( ( fp = SYS_fopen( paste_str, "rb" ) ) == NULL ) FERROR( font_not_found, paste_str ); if ( display_info && show_bitmaps_loaded ) MSGOUT( "loading \"%s\" (font)\n", paste_str ); size_t bytesread = SYS_fread( bitmreadpo, 1, stillfree, fp ); if ( bytesread == 0 ) FERROR( font_readerror, paste_str ); FntHeader *dheader = (FntHeader *) bitmreadpo; // swap endianness of FntHeader SYS_SwapFntHeader( dheader ); if ( stricmp( dheader->signature, FNT_SIGNATURE ) != 0 ) PERROR( fnt_sig_invalid ); if ( dheader->version < REQUIRED_FNT_VERSION ) PERROR( fnt_ver_invalid ); if ( dheader->width != CharsetInfo[ ftid ].srcwidth ) PERROR( fnt_inconsistency ); CharsetInfo[ ftid ].charsetpointer = bitmreadpo + sizeof( FntHeader ); bitmreadpo += bytesread; stillfree -= bytesread; SYS_fclose( fp ); charset_datasize = bytesread - sizeof( FntHeader ); } else { FILE *fp = SYS_fopen( CharsetInfo[ ftid ].file, "rb" ); if ( fp == NULL ) FERROR( font_not_found, CharsetInfo[ ftid ].file ); if ( display_info && show_bitmaps_loaded ) MSGOUT( "loading \"%s\" (font)\n", CharsetInfo[ ftid ].file ); size_t bytesread = SYS_fread( bitmreadpo, 1, stillfree, fp ); if ( bytesread == 0 ) FERROR( font_readerror, CharsetInfo[ ftid ].file ); CharsetInfo[ ftid ].charsetpointer = bitmreadpo; // set pointer to geometry data //FIXME: [momentan noch pfusch!!] if ( ftid == 1 ) CharsetInfo[ ftid ].geompointer = Char04x09Geom; else if ( ftid == 2 ) CharsetInfo[ ftid ].geompointer = Char08x08Geom; else if ( ftid == 4 ) CharsetInfo[ ftid ].geompointer = CharGoldGeom; else CharsetInfo[ ftid ].geompointer = Char16x16Geom; stillfree -= bytesread; bitmreadpo += bytesread; SYS_fclose( fp ); charset_datasize = bytesread; } // store pointer to originally loaded data (needed for different color depths) CharsetInfo[ ftid ].loadeddata = CharsetInfo[ ftid ].charsetpointer; ASSERT( CharsetInfo[ ftid ].fonttexture == NULL ); // store size of data block CharsetInfo[ ftid ].datasize = charset_datasize; // set additional info fields CharsetInfo[ ftid ].flags = 0x00000000; } if ( display_info ) { MSGOUT( "done.\n" ); } }
// read sample data into buffer ----------------------------------------------- // PRIVATE void ReadSamples() { #ifdef SAMPLES_MUST_BE_PRELOADED // exit if nothing to read if ( ( NumLoadedSamples == 0 ) && ( NumLoadedSongs == 0 ) ) return; if ( display_info ) { MSGPUT( "Loading sound data" ); if ( show_samples_loaded ) { MSGOUT( ":\n" ); } else { MSGPUT( "..." ); } } // get filesizes of samples to allocate mem in one piece size_t samplememsize = 0; for ( int i = 0; i < NumLoadedSamples; i++ ) { size_t = SYS_GetFileLength( SampleInfo[ i ].file ); if ( siz == -1 ) FERROR( sample_not_found, SampleInfo[ i ].file ); samplememsize += siz; } #ifndef DISABLE_SONGS // get filesizes of songs to allocate mem in one piece together with samples for ( i = 0; i < NumLoadedSongs; i++ ) { size_t = SYS_GetFileLength( SongInfo[ i ].file ); if ( siz == -1 ) FERROR( song_not_found, SongInfo[ i ].file ); samplememsize += siz; } #endif // allocate sample buffer (also used for songdata) if ( ( SampleMem = (char *) ALLOCMEM( samplememsize ) ) == NULL ) OUTOFMEM( no_sample_mem ); char *samplereadpo = SampleMem; size_t stillfree = samplememsize; // read in sample data for ( i = 0; i < NumLoadedSamples; i++ ) { if ( ( ( i & 0x01 ) == 0 ) && display_info && !show_samples_loaded ) MSGPUT( "." ); FILE *fp = SYS_fopen( SampleInfo[ i ].file, "rb" ); if ( fp == NULL ) FERROR( sample_not_found, SampleInfo[ i ].file ); if ( display_info && show_samples_loaded ) MSGOUT( "loading \"%s\" (sample)\n", SampleInfo[ i ].file ); size_t bytesread = SYS_fread( samplereadpo, 1, stillfree, fp ); if ( bytesread == 0 ) FERROR( sample_readerror, SampleInfo[ i ].file ); // store pointer to sample into control structure ------------ SampleInfo[ i ].samplepointer = samplereadpo; SampleInfo[ i ].size = bytesread; stillfree -= bytesread; samplereadpo += bytesread; SYS_fclose( fp ); } #ifndef DISABLE_SONGS // read in song data for ( i = 0; i < NumLoadedSongs; i++ ) { if ( ( ( i & 0x01 ) == 0 ) && display_info && !show_samples_loaded ) MSGPUT( "." ); FILE *fp = SYS_fopen( SongInfo[ i ].file, "rb" ); if ( fp == NULL ) FERROR( song_not_found, SongInfo[ i ].file ); if ( display_info && show_samples_loaded ) MSGOUT( "loading \"%s\" (song)\n", SongInfo[ i ].file ); size_t bytesread = SYS_fread( samplereadpo, 1, stillfree, fp ); if ( bytesread == 0 ) FERROR( song_readerror, SongInfo[ i ].file ); // store pointer to song into control structure -------------- SongInfo[ i ].songpointer = samplereadpo; stillfree -= bytesread; samplereadpo += bytesread; SYS_fclose( fp ); } #endif if ( display_info ) { MSGOUT( "done.\n" ); } #endif }
// read and parse optional demo header ---------------------------------------- // size_t DEMO_ParseDemoHeader( FILE *fp, int demoid, int verbose ) { ASSERT( fp != NULL ); //NOTE: // a demoid of -1 ensures that no info will be stored anywhere. // this is useful for just skipping the header (with optional // output of the contained info, without storing it anywhere). //NOTE: // if the file does not contain a valid header, the file read position // will be reset to 0, in order to allow subsequent reads to start // at the beginning of the actual data transparently. if the header // is valid but incompatible it will simply be overread. // read in header DemHeader hdr; size_t bytesread = SYS_fread( &hdr, 1, sizeof( hdr ), fp ); if ( bytesread != sizeof( hdr ) ) { SYS_fseek( fp, 0, SEEK_SET ); return 0; } // swap endianness of header SYS_SwapDemHeader( &hdr ); // test sig if ( stricmp( hdr.signature, DEM_SIGNATURE ) != 0 ) { SYS_fseek( fp, 0, SEEK_SET ); return 0; } // test version if ( hdr.version < REQUIRED_DEM_VERSION ) { SYS_fseek( fp, hdr.headersize, SEEK_SET ); return hdr.headersize; } // alloc temporary mem for info block size_t infomemlen = hdr.headersize - sizeof( hdr ); char *infomem = (char *) ALLOCMEM( infomemlen ); if ( infomem == NULL ) { SYS_fseek( fp, hdr.headersize, SEEK_SET ); return hdr.headersize; } // read info block bytesread = SYS_fread( infomem, 1, infomemlen, fp ); if ( bytesread != infomemlen ) { SYS_fseek( fp, hdr.headersize, SEEK_SET ); return hdr.headersize; } char *demotitle = NULL; char *demodesc = NULL; char *demoauthor = NULL; // read sequence of (key,value) pairs for ( char *scan = infomem; scan < infomem + infomemlen; ) { byte demokey = *scan++; switch ( demokey ) { case DEMO_KEY_TITLE: demotitle = scan; scan += strlen( scan ) + 1; break; case DEMO_KEY_DESCRIPTION: demodesc = scan; scan += strlen( scan ) + 1; break; case DEMO_KEY_AUTHOR: demoauthor = scan; scan += strlen( scan ) + 1; break; default: ASSERT( 0 ); break; } } // output info if verbose mode if ( verbose ) { if ( demotitle != NULL ) MSGOUT( "TITLE : %s", demotitle ); if ( demodesc != NULL ) MSGOUT( "DESCRIPTION: %s", demodesc ); if ( demoauthor != NULL ) MSGOUT( "AUTHOR : %s", demoauthor ); } // store info if demo id known if ( demoid != -1 ) { ASSERT( (dword)demoid < (dword)num_registered_demos ); if ( registered_demo_titles[ demoid ] != NULL ) { FREEMEM( registered_demo_titles[ demoid ] ); registered_demo_titles[ demoid ] = NULL; } if ( demotitle != NULL ) { registered_demo_titles[ demoid ] = (char *) ALLOCMEM( strlen( demotitle ) + 1 ); if ( registered_demo_titles[ demoid ] == NULL ) OUTOFMEM( 0 ); strcpy( registered_demo_titles[ demoid ], demotitle ); // convert to lower-case strlwr( registered_demo_titles[ demoid ] ); } } // free temporary info block FREEMEM( infomem ); // return size of header return hdr.headersize; }