void pilot::BinaryFileHandler::endSectionWrite() { Assertion(!_sectionOffsets.empty(), "No active section!"); auto previous_off = _sectionOffsets.back(); _sectionOffsets.pop_back(); if (previous_off.id == Section::Unnamed) { // ignore unnamed sections, these are only needed for JSON return; } size_t cur = (size_t) cftell(_cfp); Assert(cur >= previous_off.offset); size_t section_size = cur - previous_off.offset; if (section_size) { // go back to section size in file and write proper value cfseek(_cfp, (int) (cur - section_size - sizeof(int)), CF_SEEK_SET); cfwrite_int((int) section_size, _cfp); // go back to previous location for next section cfseek(_cfp, (int) cur, CF_SEEK_SET); } }
void piggy_read_sounds() { ubyte * ptr; int i, sbytes; ptr = SoundBits; sbytes = 0; for (i=0; i<Num_sound_files; i++ ) { digi_sound *snd = &GameSounds[i]; if ( SoundOffset[i] > 0 ) { if ( piggy_is_needed(i) ) { cfseek( Piggy_fp, SoundOffset[i], SEEK_SET ); // Read in the sound data!!! snd->data = ptr; ptr += snd->length; sbytes += snd->length; cfread( snd->data, snd->length, 1, Piggy_fp ); } } } mprintf(( 0, "\nActual Sound usage: %d KB\n", sbytes/1024 )); }
Section pilot::BinaryFileHandler::nextSection() { Assertion(!_in_array, "nextSection() may not be called in an array!"); if (_section_start_pos != INVALID_SIZE && _section_end_pos != INVALID_SIZE) { cf_set_max_read_len(_cfp, 0); // There was a previous section auto current = (size_t)cftell(_cfp); if (current != _section_end_pos) { mprintf(("PLR => WARNING: Advancing to the next section. " SIZE_T_ARG " bytes were skipped!\n", _section_end_pos - current)); cfseek(_cfp, (int)_section_end_pos, CF_SEEK_SET); } _section_start_pos = INVALID_SIZE; _section_end_pos = INVALID_SIZE; } auto section_id = cfread_ushort(_cfp); auto size = cfread_uint(_cfp); if (size == 0) { return Section::Invalid; } _section_start_pos = (size_t)cftell(_cfp); _section_end_pos = _section_start_pos + size; cf_set_max_read_len(_cfp, size); return static_cast<Section>(section_id); }
unsigned char anim_instance_get_byte(anim_instance *ai, int offset) { int absolute_offset; anim *parent; Assert(ai); Assert(ai->parent->cfile_ptr); Assert(ai->parent->flags & ANF_STREAMED); parent = ai->parent; absolute_offset = ai->file_offset + offset; // maybe in cache? int cache_offset; cache_offset = absolute_offset - parent->cache_file_offset; if ( (cache_offset >= 0) && (cache_offset < ANI_STREAM_CACHE_SIZE) ) { return parent->cache[cache_offset]; } else { // fill cache cfseek(parent->cfile_ptr, absolute_offset, CF_SEEK_SET); cfread(parent->cache, ANI_STREAM_CACHE_SIZE, 1, parent->cfile_ptr); parent->cache_file_offset = absolute_offset; return parent->cache[0]; } }
/* * @brief send animation to its 1st frame * * @note headers must be read before this function can be called */ void apng_ani::goto_start() { current_frame = 0; if (_cache == false ) { // only required if not caching frames if (cfseek(_cfp, _frame_offsets.at(0), CF_SEEK_SET) != 0) { _apng_failed("couldn't seek to 1st fcTL offset"); } } }
// given a valid XSTR() id#, lookup the string in tstrings.tbl, filling in out if found, nonzero on success int lcl_ext_lookup(char *out, int id) { char text[1024]; int ret; int pointer; Assert(Lcl_pointer_count >= 0); Assert(Lcl_pointers[0] >= 0); Assert(Lcl_pointers[Lcl_pointer_count - 1] >= 0); Assert(Lcl_ext_file != NULL); Assert(id >= 0); // seek to the closest pointer <= the id# we're looking for pointer = id / LCL_GRANULARITY; cfseek(Lcl_ext_file, Lcl_pointers[pointer], CF_SEEK_SET); // reset parsing vars and go to town Ts_current_state = TS_SCANNING; Ts_id_text_size = 0; Ts_text_size; memset(Ts_text, 0, PARSE_TEXT_STRING_LEN); memset(Ts_id_text, 0, PARSE_ID_STRING_LEN); while((cftell(Lcl_ext_file) < Lcl_pointers[Lcl_pointer_count - 1]) && cfgets(text, 1024, Lcl_ext_file)){ ret = lcl_ext_lookup_sub(text, out, id); // run the line parse function switch(ret & 0x0fffffff){ // error case 0 : Int3(); // should never get here - it means the string doens't exist in the table!! return 0; // success parsing the line - please continue case 1 : break; // found a matching string/id pair case 2 : // success if (Lcl_gr) { // this is because tstrings.tbl reads in as ANSI for some reason // opening tstrings with "rb" mode didnt seem to help, so its now still "rt" like before lcl_fix_umlauts(out, LCL_TO_ASCII); } return 1; // end of language found case 3 : Int3(); // should never get here - it means the string doens't exist in the table!! return 0; } } Int3(); // should never get here - it means the string doens't exist in the table!! return 0; }
void pilotfile::endSection() { Assert( cfp ); Assert( m_size_offset > 0 ); size_t cur = cftell(cfp); Assert( cur >= m_size_offset ); size_t section_size = cur - m_size_offset; if (section_size) { // go back to section size in file and write proper value cfseek(cfp, cur - section_size - sizeof(int), CF_SEEK_SET); cfwrite_int((int)section_size, cfp); // go back to previous location for next section cfseek(cfp, cur, CF_SEEK_SET); } }
// reads header information from the PCX file into the bitmap pointer int pcx_read_header(char *real_filename, int *w, int *h, ubyte *pal ) { PCXHeader header; CFILE * PCXfile; char filename[MAX_FILENAME_LEN]; strcpy( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat( filename, ".pcx" ); PCXfile = cfopen( filename , "rb" ); if ( !PCXfile ) return PCX_ERROR_OPENING; // read 128 char PCX header if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { cfclose( PCXfile ); return PCX_ERROR_NO_HEADER; } header.Xmin = INTEL_SHORT( header.Xmin ); header.Ymin = INTEL_SHORT( header.Ymin ); header.Xmax = INTEL_SHORT( header.Xmax ); header.Ymax = INTEL_SHORT( header.Ymax ); header.Hdpi = INTEL_SHORT( header.Hdpi ); header.Vdpi = INTEL_SHORT( header.Vdpi ); for ( int i=0; i<16; i++ ){ for ( int j=0; j<3; j++){ header.ColorMap[i][j] = INTEL_INT( header.ColorMap[i][j] ); } } header.BytesPerLine = INTEL_SHORT( header.BytesPerLine ); for ( int i=0; i<60; i++ ){ header.filler[i] = INTEL_INT( header.filler[i] ); } // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { cfclose( PCXfile ); return PCX_ERROR_WRONG_VERSION; } if (w) *w = header.Xmax - header.Xmin + 1; if (h) *h = header.Ymax - header.Ymin + 1; if ( pal ) { cfseek( PCXfile, -768, CF_SEEK_END ); cfread( pal, 3, 256, PCXfile ); } cfclose(PCXfile); return PCX_ERROR_NONE; }
// reads header information from the PCX file into the bitmap pointer int pcx_read_header(char *real_filename, int *w, int *h, ubyte *pal ) { PCXHeader header; CFILE * PCXfile; char filename[MAX_FILENAME_LEN]; strcpy( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat( filename, ".pcx" ); PCXfile = cfopen( filename , "rb" ); if ( !PCXfile ) return PCX_ERROR_OPENING; // read 128 char PCX header if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { cfclose( PCXfile ); return PCX_ERROR_NO_HEADER; } // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { cfclose( PCXfile ); return PCX_ERROR_WRONG_VERSION; } if (w) *w = header.Xmax - header.Xmin + 1; if (h) *h = header.Ymax - header.Ymin + 1; if ( pal ) { cfseek( PCXfile, -768, CF_SEEK_END ); cfread( pal, 3, 256, PCXfile ); } cfclose(PCXfile); return PCX_ERROR_NONE; }
void piggy_bitmap_page_in( bitmap_index bitmap ) { grs_bitmap * bmp; int i,org_i,temp; i = bitmap.index; Assert( i >= 0 ); Assert( i < MAX_BITMAP_FILES ); Assert( i < Num_bitmap_files ); Assert( Piggy_bitmap_cache_size > 0 ); if ( i < 1 ) return; if ( i >= MAX_BITMAP_FILES ) return; if ( i >= Num_bitmap_files ) return; if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!! if ( piggy_low_memory ) { org_i = i; i = GameBitmapXlat[i]; // Xlat for low-memory settings! } bmp = &GameBitmaps[i]; if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) { stop_time(); ReDoIt: descent_critical_error = 0; cfseek(Piggy_fp, GameBitmapOffset[i], SEEK_SET); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]; bmp->bm_flags = GameBitmapFlags[i]; if ( bmp->bm_flags & BM_FLAG_RLE ) { int zsize = 0; descent_critical_error = 0; // This fails consistently the first time it's called... // Would be nice to not have to redo every time temp = cfread( &zsize, 1, sizeof(int), Piggy_fp ); if (temp == EOF) goto ReDoIt; if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } // GET JOHN NOW IF YOU GET THIS ASSERT!!! Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size ); if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) { piggy_bitmap_page_out_all(); goto ReDoIt; } memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) ); Piggy_bitmap_cache_next += sizeof(int); descent_critical_error = 0; temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } Piggy_bitmap_cache_next += zsize-4; } else { // GET JOHN NOW IF YOU GET THIS ASSERT!!! Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size ); if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) { piggy_bitmap_page_out_all(); goto ReDoIt; } descent_critical_error = 0; temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w; } if ( bmp->bm_selector ) { if (!dpmi_modify_selector_base( bmp->bm_selector, bmp->bm_data )) Error( "Error modifying selector base in piggy.c\n" ); } start_time(); } if ( piggy_low_memory ) { if ( org_i != i ) GameBitmaps[org_i] = GameBitmaps[i]; } }
/* * @brief Get info about the apng * @note Also validates the apng & sets it up to have frames read * * @retval PNG_ERROR_NONE (0), otherwise will raise exception */ int apng_ani::load_header() { char filename[MAX_FILENAME_LEN]; strcpy_s(filename, _filename.c_str()); char *p = strchr( filename, '.' ); if ( p != nullptr ) *p = 0; strcat_s( filename, ".png" ); _cfp = cfopen( filename , "rb" ); if ( _cfp == nullptr) { _apng_failed("couldn't open filename"); } _reading = true; ubyte sig[8]; if (cfread(sig, 8, 1, _cfp) != 1) { _apng_failed("cfread of png signature failed"); } if (png_sig_cmp(sig, 0, 8) != 0) { _apng_failed("file has invalid png signature"); } // setup chunk sizes before use _chunk_IHDR.data.resize(25); // fixed IHDR chunk size _chunk.data.resize(25); // match the other sizes, maybe waste up to 13 bytes (ooooh) _id = _read_chunk(_chunk_IHDR); if (_id != id_IHDR || _chunk_IHDR.size != 25) { _apng_failed("failed to read IHDR chunk"); } w = png_get_uint_32(&_chunk_IHDR.data[8]); h = png_get_uint_32(&_chunk_IHDR.data[12]); _row_len = w * 4; // setup frames & keep bm_create happy _image_size = _row_len * h; frame.data.reserve(_image_size); // alloc only once frame.data.assign(_image_size, 0); // all transparent black per spec frame.rows.resize(h); _frame_raw.data.resize(_image_size); _frame_raw.rows.resize(h); _frame_next.data.resize(_image_size); _frame_next.rows.resize(h); for (uint i = 0; i < h; ++i) { // everything is correctly sized above; avoid .at() error checks frame.rows[i] = &frame.data[i * _row_len]; _frame_raw.rows[i] = &_frame_raw.data[i * _row_len]; _frame_next.rows[i] = &_frame_next.data[i * _row_len]; } // read all data while (!cfeof(_cfp)) { _process_chunk(); } // should be at EOF; attach to _frame_offsets to make next_frame code simpler Assertion(cfeof(_cfp) != 0, "apng not at EOF, get a coder!"); _frame_offsets.push_back(cftell(_cfp)); // sanity checks if (anim_time <= 0.0f) { _apng_failed("animation duration <= 0.0f, bad data?"); } if (nframes < 1) { _apng_failed("animation didn't have any frames, is this a static png?"); } // back to start, including reset of _cfp so it can be used for the 1st frame _reading = false; if (cfseek(_cfp, _frame_offsets.at(0), CF_SEEK_SET) != 0) { _apng_failed("couldn't seek to 1st fcTL offset"); } return PNG_ERROR_NONE; }
int piggy_init() { int sbytes = 0; char temp_name_read[16]; char temp_name[16]; grs_bitmap temp_bitmap; digi_sound temp_sound; DiskBitmapHeader bmh; DiskSoundHeader sndh; int header_size, N_bitmaps, N_sounds; int i,size, length, x, y; char * filename; int read_sounds = 1; int Pigdata_start; hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES ); hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES ); if ( FindArg( "-nosound" ) || (digi_driver_board<1) ) { read_sounds = 0; mprintf(( 0, "Not loading sound data!!!!!\n" )); } for (i=0; i<MAX_SOUND_FILES; i++ ) { GameSounds[i].length = 0; GameSounds[i].data = NULL; SoundOffset[i] = 0; } for (i=0; i<MAX_BITMAP_FILES; i++ ) { GameBitmapXlat[i] = i; GameBitmaps[i].bm_flags = BM_FLAG_PAGED_OUT; } if ( !bogus_bitmap_initialized ) { int i; ubyte c; bogus_bitmap_initialized = 1; memset( &bogus_bitmap, 0, sizeof(grs_bitmap) ); bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64; bogus_bitmap.bm_data = bogus_data; c = gr_find_closest_color( 0, 0, 63 ); for (i=0; i<4096; i++ ) bogus_data[i] = c; c = gr_find_closest_color( 63, 0, 0 ); // Make a big red X ! for (i=0; i<64; i++ ) { bogus_data[i*64+i] = c; bogus_data[i*64+(63-i)] = c; } piggy_register_bitmap( &bogus_bitmap, "bogus", 1 ); bogus_sound.length = 64*64; bogus_sound.data = bogus_data; GameBitmapOffset[0] = 0; } filename = "DESCENT.PIG"; if ( FindArg( "-bigpig" )) BigPig = 1; if ( FindArg( "-lowmem" )) piggy_low_memory = 1; if ( FindArg( "-nolowmem" )) piggy_low_memory = 0; if (piggy_low_memory) digi_lomem = 1; if ( (i=FindArg( "-piggy" )) ) { filename = Args[i+1]; mprintf( (0, "Using alternate pigfile, '%s'\n", filename )); } Piggy_fp = cfopen( filename, "rb" ); if (Piggy_fp==NULL) return 0; cfread( &Pigdata_start, sizeof(int), 1, Piggy_fp ); #ifdef EDITOR if ( FindArg("-nobm") ) #endif { bm_read_all( Piggy_fp ); // Note connection to above if!!! cfread( GameBitmapXlat, sizeof(ushort)*MAX_BITMAP_FILES, 1, Piggy_fp ); } cfseek( Piggy_fp, Pigdata_start, SEEK_SET ); size = cfilelength(Piggy_fp) - Pigdata_start; length = size; mprintf( (0, "\nReading data (%d KB) ", size/1024 )); cfread( &N_bitmaps, sizeof(int), 1, Piggy_fp ); size -= sizeof(int); cfread( &N_sounds, sizeof(int), 1, Piggy_fp ); size -= sizeof(int); header_size = (N_bitmaps*sizeof(DiskBitmapHeader)) + (N_sounds*sizeof(DiskSoundHeader)); x = 60; y = 189 * f2fl(Scale_y); gr_set_curfont( Gamefonts[GFONT_SMALL] ); gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 ); gr_scale_printf( 0x8000, y-10*f2fl(Scale_y), Scale_factor, Scale_factor, "%s...", TXT_LOADING_DATA ); #ifdef OGLES showRenderBuffer(); #endif for (i=0; i<N_bitmaps; i++ ) { cfread( &bmh, sizeof(DiskBitmapHeader), 1, Piggy_fp ); //size -= sizeof(DiskBitmapHeader); memcpy( temp_name_read, bmh.name, 8 ); temp_name_read[8] = 0; if ( bmh.dflags & DBM_FLAG_ABM ) sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 ); else strcpy( temp_name, temp_name_read ); memset( &temp_bitmap, 0, sizeof(grs_bitmap) ); if ( bmh.dflags & DBM_FLAG_LARGE ) temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width+256; else temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width; temp_bitmap.bm_h = bmh.height; temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT; temp_bitmap.avg_color = bmh.avg_color; temp_bitmap.bm_data = Piggy_bitmap_cache_data; #ifdef OGLES temp_bitmap.bm_ogles_tex_id = 0; #endif GameBitmapFlags[i+1] = 0; if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT; if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT; if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING; if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE; GameBitmapOffset[i+1] = bmh.offset + header_size + (sizeof(int)*2) + Pigdata_start; Assert( (i+1) == Num_bitmap_files ); piggy_register_bitmap( &temp_bitmap, temp_name, 1 ); } for (i=0; i<N_sounds; i++ ) { cfread( &sndh, sizeof(DiskSoundHeader), 1, Piggy_fp ); //size -= sizeof(DiskSoundHeader); temp_sound.length = sndh.length; temp_sound.data = (ubyte *)(sndh.offset + header_size + (sizeof(int)*2)+Pigdata_start); SoundOffset[Num_sound_files] = sndh.offset + header_size + (sizeof(int)*2)+Pigdata_start; memcpy( temp_name_read, sndh.name, 8 ); temp_name_read[8] = 0; piggy_register_sound( &temp_sound, temp_name_read, 1 ); sbytes += sndh.length; //mprintf(( 0, "%d bytes of sound\n", sbytes )); } SoundBits = malloc( sbytes + 16 ); if ( SoundBits == NULL ) Error( "Not enough memory to load DESCENT.PIG sounds\n" ); #ifdef EDITOR Piggy_bitmap_cache_size = size - header_size - sbytes + 16; Assert( Piggy_bitmap_cache_size > 0 ); #else Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE; #endif BitmapBits = malloc( Piggy_bitmap_cache_size ); if ( BitmapBits == NULL ) Error( "Not enough memory to load DESCENT.PIG bitmaps\n" ); Piggy_bitmap_cache_data = BitmapBits; Piggy_bitmap_cache_next = 0; mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 )); atexit(piggy_close_file); // mprintf( (0, "<<<<Paging in all piggy bitmaps...>>>>>" )); // for (i=0; i < Num_bitmap_files; i++ ) { // bitmap_index bi; // bi.index = i; // PIGGY_PAGE_IN( bi ); // } // mprintf( (0, "\n (USed %d / %d KB)\n", Piggy_bitmap_cache_next/1024, (size - header_size - sbytes + 16)/1024 )); // key_getch(); return 0; }
/* * get_csg_rank: this function is called from plr.cpp & is * tightly linked with pilotfile::verify() */ bool pilotfile::get_csg_rank(int *rank) { player t_csg; // set player ptr first thing p = &t_csg; // filename has already been set cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("CSG => Unable to open '%s'!\n", filename.c_str())); return false; } unsigned int csg_id = cfread_uint(cfp); if (csg_id != CSG_FILE_ID) { mprintf(("CSG => Invalid header id for '%s'!\n", filename.c_str())); csg_close(); return false; } // version, now used csg_ver = cfread_ubyte(cfp); mprintf(("CSG => Get Rank from '%s' with version %d...\n", filename.c_str(), (int)csg_ver)); // the point of all this: read in the CSG contents while ( !m_have_flags && !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); size_t offset_pos; // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("CSG => Parsing: Flags...\n")); m_have_flags = true; csg_read_flags(); break; default: break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("CSG => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("CSG => ERROR: %s\n", err)); csg_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("CSG => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, (int)offset_pos, CF_SEEK_CUR); } } // this is what we came for... *rank = p->stats.rank; mprintf(("CSG => Get Rank complete!\n")); // cleanup & return csg_close(); return true; }
//int pcx_read_bitmap_16bpp( char * real_filename, ubyte *org_data, ubyte bpp, int aabitmap, int nondark ) int pcx_read_bitmap( const char * real_filename, ubyte *org_data, ubyte *pal, int byte_size, int aabitmap, int nondark, int cf_type ) { PCXHeader header; CFILE * PCXfile; int row, col, count, xsize, ysize; ubyte data=0; int buffer_size, buffer_pos; ubyte buffer[1024]; ubyte *pixdata; char filename[MAX_FILENAME_LEN]; ubyte palette[768]; ushort bit_16; COLOR32 bit_32; ubyte r, g, b, al; strcpy_s( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat_s( filename, ".pcx" ); PCXfile = cfopen( filename , "rb", CFILE_NORMAL, cf_type ); if ( !PCXfile ){ return PCX_ERROR_OPENING; } // read 128 char PCX header if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { cfclose( PCXfile ); return PCX_ERROR_NO_HEADER; } header.Xmin = INTEL_SHORT( header.Xmin ); //-V570 header.Ymin = INTEL_SHORT( header.Ymin ); //-V570 header.Xmax = INTEL_SHORT( header.Xmax ); //-V570 header.Ymax = INTEL_SHORT( header.Ymax ); //-V570 header.Hdpi = INTEL_SHORT( header.Hdpi ); //-V570 header.Vdpi = INTEL_SHORT( header.Vdpi ); //-V570 header.BytesPerLine = INTEL_SHORT( header.BytesPerLine ); //-V570 // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { cfclose( PCXfile ); return PCX_ERROR_WRONG_VERSION; } // Find the size of the image xsize = header.Xmax - header.Xmin + 1; ysize = header.Ymax - header.Ymin + 1; // Read the extended palette at the end of PCX file // Read in a character which should be 12 to be extended palette file cfseek( PCXfile, -768, CF_SEEK_END ); cfread( palette, 1, (3 * 256), PCXfile ); cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET ); buffer_size = 1024; buffer_pos = 0; // Assert( buffer_size == 1024 ); // AL: removed to avoid optimized warning 'unreachable code' buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); count = 0; for (row=0; row<ysize;row++) { pixdata = org_data; for (col=0; col<header.BytesPerLine;col++) { if ( count == 0 ) { data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } if ((data & 0xC0) == 0xC0) { count = data & 0x3F; data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } } else { count = 1; } } // stuff the pixel if ( col < xsize ) { // 8-bit PCX reads if ( byte_size == 1 ) { *pixdata++ = data; } else { // 16-bit AABITMAP reads if ( (byte_size == 2) && aabitmap ) { // stuff the pixel // memcpy(pixdata, &data, 2); *((ushort*)pixdata) = (ushort)data; } else { // stuff the 24 bit value r = palette[data*3]; g = palette[data*3 + 1]; b = palette[data*3 + 2]; // clear the pixel bit_16 = 0; memset(&bit_32, 0, sizeof(COLOR32)); // 16-bit non-darkening reads if ( (byte_size == 2) && nondark ) { al = 0; if (palman_is_nondarkening(r, g, b)) { al = 255; } } else { // if the color matches the transparent color, make it so al = 255; if ( (0 == (int)palette[data*3]) && (255 == (int)palette[data*3+1]) && (0 == (int)palette[data*3+2]) ) { r = b = 0; g = (byte_size == 4) ? 0 : 255; al = 0; } } // normal 16-bit reads if ( byte_size == 2 ) { // stuff the color bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al); // stuff the pixel *((ushort*)pixdata) = bit_16; } // normal 32-bit reads else if ( byte_size == 4 ) { if ( /*(r == 0) && (b == 0) && (g == 255) && (al == 0)*/ 0 ) { memset(&bit_32, 0, sizeof(COLOR32)); } else { bit_32.r = r; bit_32.g = g; bit_32.b = b; bit_32.a = al; } // stuff the pixel *((COLOR32*)pixdata) = bit_32; } } pixdata += byte_size; } } count--; } org_data += (xsize * byte_size); } cfclose(PCXfile); return PCX_ERROR_NONE; }
int pcx_read_bitmap_16bpp_nondark( char * real_filename, ubyte *org_data ) { PCXHeader header; CFILE * PCXfile; int row, col, count, xsize, ysize; ubyte data=0; int buffer_size, buffer_pos; ubyte buffer[1024]; ubyte *pixdata; char filename[MAX_FILENAME_LEN]; ubyte palette[768]; ushort bit_16; ubyte r, g, b, al; strcpy( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat( filename, ".pcx" ); PCXfile = cfopen( filename , "rb" ); if ( !PCXfile ){ return PCX_ERROR_OPENING; } // read 128 char PCX header if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { cfclose( PCXfile ); return PCX_ERROR_NO_HEADER; } header.Xmin = INTEL_SHORT( header.Xmin ); header.Ymin = INTEL_SHORT( header.Ymin ); header.Xmax = INTEL_SHORT( header.Xmax ); header.Ymax = INTEL_SHORT( header.Ymax ); header.Hdpi = INTEL_SHORT( header.Hdpi ); header.Vdpi = INTEL_SHORT( header.Vdpi ); header.BytesPerLine = INTEL_SHORT( header.BytesPerLine ); // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { cfclose( PCXfile ); return PCX_ERROR_WRONG_VERSION; } // Find the size of the image xsize = header.Xmax - header.Xmin + 1; ysize = header.Ymax - header.Ymin + 1; // Read the extended palette at the end of PCX file // Read in a character which should be 12 to be extended palette file cfseek( PCXfile, -768, CF_SEEK_END ); cfread( palette, 3, 256, PCXfile ); cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET ); buffer_size = 1024; buffer_pos = 0; // Assert( buffer_size == 1024 ); // AL: removed to avoid optimized warning 'unreachable code' buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); count = 0; for (row=0; row<ysize;row++) { pixdata = org_data; for (col=0; col<header.BytesPerLine;col++) { if ( count == 0 ) { data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } if ((data & 0xC0) == 0xC0) { count = data & 0x3F; data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } } else { count = 1; } } // stuff the pixel if ( col < xsize ){ // stuff the 24 bit value r = palette[data*3]; g = palette[data*3 + 1]; b = palette[data*3 + 2]; // if this is a nondarkening texture // if this color matches a nondarkening pixel color, set the alpha to high al = 0; if(palman_is_nondarkening(r, g, b)){ al = 255; } // set the pixel bit_16 = 0; bm_set_components((ubyte*)&bit_16, &r, &g, &b, &al); // stuff the pixel *((ushort*)pixdata) = bit_16; pixdata += 2; } count--; } org_data += (xsize * 2); } cfclose(PCXfile); return PCX_ERROR_NONE; }
/** * @brief Load an animation. This stores the compressed data, which instances of the animation can reference. * Must be free'ed later with anim_free(). * * @param real_filename Filename of animation * @param cf_dir_type * @param file_mapped Whether to use memory-mapped file or not. * * @details Memory-mapped files will page in the animation from disk as it is needed, but performance is not as good. * @return Pointer to anim that is loaded if sucess, NULL if failure. */ anim *anim_load(char *real_filename, int cf_dir_type, int file_mapped) { anim *ptr; CFILE *fp; int count,idx; char name[_MAX_PATH]; Assert( real_filename != NULL ); strcpy_s( name, real_filename ); char *p = strchr( name, '.' ); if ( p ) { *p = 0; } strcat_s( name, ".ani" ); ptr = first_anim; while (ptr) { if (!stricmp(name, ptr->name)) break; ptr = ptr->next; } if (!ptr) { fp = cfopen(name, "rb", CFILE_NORMAL, cf_dir_type); if ( !fp ) return NULL; ptr = (anim *) vm_malloc(sizeof(anim)); Assert(ptr); ptr->flags = 0; ptr->next = first_anim; first_anim = ptr; Assert(strlen(name) < _MAX_PATH - 1); strcpy_s(ptr->name, name); ptr->instance_count = 0; ptr->width = 0; ptr->height = 0; ptr->total_frames = 0; ptr->keys = NULL; ptr->ref_count=0; anim_read_header(ptr, fp); if(ptr->num_keys > 0){ ptr->keys = (key_frame*)vm_malloc(sizeof(key_frame) * ptr->num_keys); Assert(ptr->keys != NULL); } // store how long the anim should take on playback (in seconds) ptr->time = i2fl(ptr->total_frames)/ptr->fps; for(idx=0;idx<ptr->num_keys;idx++){ ptr->keys[idx].frame_num = 0; cfread(&ptr->keys[idx].frame_num, 2, 1, fp); cfread(&ptr->keys[idx].offset, 4, 1, fp); ptr->keys[idx].frame_num = INTEL_INT( ptr->keys[idx].frame_num ); //-V570 ptr->keys[idx].offset = INTEL_INT( ptr->keys[idx].offset ); //-V570 } cfread(&count, 4, 1, fp); // size of compressed data count = INTEL_INT( count ); ptr->cfile_ptr = NULL; if ( file_mapped == PAGE_FROM_MEM) { // Try mapping the file to memory ptr->flags |= ANF_MEM_MAPPED; ptr->cfile_ptr = cfopen(name, "rb", CFILE_MEMORY_MAPPED, cf_dir_type); } // couldn't memory-map file... must be in a packfile, so stream manually if ( file_mapped && !ptr->cfile_ptr ) { ptr->flags &= ~ANF_MEM_MAPPED; ptr->flags |= ANF_STREAMED; ptr->cfile_ptr = cfopen(name, "rb", CFILE_NORMAL, cf_dir_type); } ptr->cache = NULL; // If it opened properly as mem-mapped (or streamed) if (ptr->cfile_ptr != NULL) { // VERY IMPORTANT STEP // Set the data pointer to the compressed data (which is not at the start of the // file). Use ftell() to find out how far we've already parsed into the file // int offset; offset = cftell(fp); ptr->file_offset = offset; if ( ptr->flags & ANF_STREAMED ) { ptr->data = NULL; ptr->cache_file_offset = ptr->file_offset; ptr->cache = (ubyte*)vm_malloc(ANI_STREAM_CACHE_SIZE+2); Assert(ptr->cache); cfseek(ptr->cfile_ptr, offset, CF_SEEK_SET); cfread(ptr->cache, ANI_STREAM_CACHE_SIZE, 1, ptr->cfile_ptr); } else { ptr->data = (ubyte*)cf_returndata(ptr->cfile_ptr) + offset; } } else { // Not a memory mapped file (or streamed) ptr->flags &= ~ANF_MEM_MAPPED; ptr->flags &= ~ANF_STREAMED; ptr->data = (ubyte *) vm_malloc(count); ptr->file_offset = -1; cfread(ptr->data, count, 1, fp); } cfclose(fp); // store screen signature, so we can tell if palette changes ptr->screen_sig = gr_screen.signature; anim_set_palette(ptr); } ptr->ref_count++; return ptr; }
hmp_file *hmp_open(const char *filename) { int i, data, num_tracks, tempo; char buf[256]; CFILE *fp; hmp_file *hmp; unsigned char *p; if (!(fp = cfopen((char *)filename, "rb"))) return NULL; MALLOC(hmp, hmp_file, 1); if (!hmp) { cfclose(fp); return NULL; } memset(hmp, 0, sizeof(*hmp)); if ((cfread(buf, 1, 8, fp) != 8) || (memcmp(buf, "HMIMIDIP", 8))) { cfclose(fp); hmp_close(hmp); return NULL; } if (cfseek(fp, 0x30, SEEK_SET)) { cfclose(fp); hmp_close(hmp); return NULL; } if (cfread(&num_tracks, 4, 1, fp) != 1) { cfclose(fp); hmp_close(hmp); return NULL; } if ((num_tracks < 1) || (num_tracks > HMP_TRACKS)) { cfclose(fp); hmp_close(hmp); return NULL; } hmp->num_trks = num_tracks; if (cfseek(fp, 0x38, SEEK_SET)) { cfclose(fp); hmp_close(hmp); return NULL; } if (cfread(&tempo, 4, 1, fp) != 1) { cfclose(fp); hmp_close(hmp); return NULL; } hmp->tempo = INTEL_INT(tempo); if (cfseek(fp, 0x308, SEEK_SET)) { cfclose(fp); hmp_close(hmp); return NULL; } for (i = 0; i < num_tracks; i++) { if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(&data, 4, 1, fp) != 1)) { cfclose(fp); hmp_close(hmp); return NULL; } data -= 12; hmp->trks[i].len = data; MALLOC(p, unsigned char, data); if (!(hmp->trks[i].data = p)) { cfclose(fp); hmp_close(hmp); return NULL; } /* finally, read track data */ if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(p, data, 1, fp) != 1)) { cfclose(fp); hmp_close(hmp); return NULL; } } cfclose(fp); return hmp; }
int generic_anim_stream(generic_anim *ga, const bool cache) { CFILE *img_cfp = NULL; int anim_fps = 0; char full_path[MAX_PATH]; int size = 0, offset = 0; const int NUM_TYPES = 3; const ubyte type_list[NUM_TYPES] = {BM_TYPE_EFF, BM_TYPE_ANI, BM_TYPE_PNG}; const char *ext_list[NUM_TYPES] = {".eff", ".ani", ".png"}; int rval = -1; int bpp; ga->type = BM_TYPE_NONE; rval = cf_find_file_location_ext(ga->filename, NUM_TYPES, ext_list, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0); // could not be found, or is invalid for some reason if ( (rval < 0) || (rval >= NUM_TYPES) ) return -1; //make sure we can open it img_cfp = cfopen_special(full_path, "rb", size, offset, CF_TYPE_ANY); if (img_cfp == NULL) { return -1; } strcat_s(ga->filename, ext_list[rval]); ga->type = type_list[rval]; //seek to the end cfseek(img_cfp, 0, CF_SEEK_END); cfclose(img_cfp); if(ga->type == BM_TYPE_ANI) { bpp = ANI_BPP_CHECK; if(ga->use_hud_color) bpp = 8; if (ga->ani.animation == nullptr) { ga->ani.animation = anim_load(ga->filename, CF_TYPE_ANY, 0); } if (ga->ani.instance == nullptr) { ga->ani.instance = init_anim_instance(ga->ani.animation, bpp); } #ifndef NDEBUG // for debug of ANI sizes strcpy_s(ga->ani.animation->name, ga->filename); #endif ga->num_frames = ga->ani.animation->total_frames; anim_fps = ga->ani.animation->fps; ga->height = ga->ani.animation->height; ga->width = ga->ani.animation->width; ga->buffer = ga->ani.instance->frame; ga->bitmap_id = bm_create(bpp, ga->width, ga->height, ga->buffer, (bpp==8)?BMP_AABITMAP:0); ga->ani.instance->last_bitmap = -1; ga->ani.instance->file_offset = ga->ani.animation->file_offset; ga->ani.instance->data = ga->ani.animation->data; ga->previous_frame = -1; } else if (ga->type == BM_TYPE_PNG) { if (ga->png.anim == nullptr) { try { ga->png.anim = new apng::apng_ani(ga->filename, cache); } catch (const apng::ApngException& e) { mprintf(("Failed to load apng: %s\n", e.what() )); delete ga->png.anim; ga->png.anim = nullptr; return -1; } nprintf(("apng", "apng read OK (%ix%i@%i) duration (%f)\n", ga->png.anim->w, ga->png.anim->h, ga->png.anim->bpp, ga->png.anim->anim_time)); } ga->png.anim->goto_start(); ga->current_frame = 0; ga->png.previous_frame_time = 0.0f; ga->num_frames = ga->png.anim->nframes; ga->height = ga->png.anim->h; ga->width = ga->png.anim->w; ga->previous_frame = -1; ga->buffer = ga->png.anim->frame.data.data(); ga->bitmap_id = bm_create(ga->png.anim->bpp, ga->width, ga->height, ga->buffer, 0); } else { bpp = 32; if(ga->use_hud_color) bpp = 8; bm_load_and_parse_eff(ga->filename, CF_TYPE_ANY, &ga->num_frames, &anim_fps, &ga->keyframe, 0); char *p = strrchr( ga->filename, '.' ); if ( p ) *p = 0; char frame_name[MAX_FILENAME_LEN]; snprintf(frame_name, MAX_FILENAME_LEN, "%s_0000", ga->filename); ga->bitmap_id = bm_load(frame_name); if(ga->bitmap_id < 0) { mprintf(("Cannot find first frame for eff streaming. eff Filename: %s", ga->filename)); return -1; } snprintf(frame_name, MAX_FILENAME_LEN, "%s_0001", ga->filename); ga->eff.next_frame = bm_load(frame_name); bm_get_info(ga->bitmap_id, &ga->width, &ga->height); ga->previous_frame = 0; } // keyframe info if (ga->type == BM_TYPE_ANI) { //we only care if there are 2 keyframes - first frame, other frame to jump to for ship/weapons //mainhall door anis hav every frame as keyframe, so we don't care //other anis only have the first frame if(ga->ani.animation->num_keys == 2) { int key1 = ga->ani.animation->keys[0].frame_num; int key2 = ga->ani.animation->keys[1].frame_num; if (key1 < 0 || key1 >= ga->num_frames) key1 = -1; if (key2 < 0 || key2 >= ga->num_frames) key2 = -1; // some retail anis have their keyframes reversed // and some have their keyframes out of bounds if (key1 >= 0 && key1 >= key2) { ga->keyframe = ga->ani.animation->keys[0].frame_num; ga->keyoffset = ga->ani.animation->keys[0].offset; } else if (key2 >= 0 && key2 >= key1) { ga->keyframe = ga->ani.animation->keys[1].frame_num; ga->keyoffset = ga->ani.animation->keys[1].offset; } } } ga->streaming = 1; if (ga->type == BM_TYPE_PNG) { ga->total_time = ga->png.anim->anim_time; } else { if (anim_fps == 0) { Error(LOCATION, "animation (%s) has invalid fps of zero, fix this!", ga->filename); } ga->total_time = ga->num_frames / (float) anim_fps; } ga->done_playing = 0; ga->anim_time = 0.0f; return 0; }
// ----------------------------------------------------------------------------- //loads from an already-open file // returns 0=everything ok, 1=old version, -1=error int load_mine_data(CFILE *LoadFile) { int i, j; short tmap_xlate; int translate; char *temptr; int mine_start = cftell(LoadFile); fuelcen_reset(); for (i=0; i<MAX_TEXTURES; i++ ) tmap_times_used[i] = 0; #ifdef EDITOR // Create a new mine to initialize things. //texpage_goto_first(); create_new_mine(); #endif //===================== READ FILE INFO ======================== // These are the default values... version and fileinfo_sizeof // don't have defaults. mine_fileinfo.header_offset = -1; mine_fileinfo.header_size = sizeof(mine_header); mine_fileinfo.editor_offset = -1; mine_fileinfo.editor_size = sizeof(mine_editor); mine_fileinfo.vertex_offset = -1; mine_fileinfo.vertex_howmany = 0; mine_fileinfo.vertex_sizeof = sizeof(vms_vector); mine_fileinfo.segment_offset = -1; mine_fileinfo.segment_howmany = 0; mine_fileinfo.segment_sizeof = sizeof(segment); mine_fileinfo.newseg_verts_offset = -1; mine_fileinfo.newseg_verts_howmany = 0; mine_fileinfo.newseg_verts_sizeof = sizeof(vms_vector); mine_fileinfo.group_offset = -1; mine_fileinfo.group_howmany = 0; mine_fileinfo.group_sizeof = sizeof(group); mine_fileinfo.texture_offset = -1; mine_fileinfo.texture_howmany = 0; mine_fileinfo.texture_sizeof = 13; // num characters in a name mine_fileinfo.walls_offset = -1; mine_fileinfo.walls_howmany = 0; mine_fileinfo.walls_sizeof = sizeof(wall); mine_fileinfo.triggers_offset = -1; mine_fileinfo.triggers_howmany = 0; mine_fileinfo.triggers_sizeof = sizeof(trigger); mine_fileinfo.object_offset = -1; mine_fileinfo.object_howmany = 1; mine_fileinfo.object_sizeof = sizeof(object); // Read in mine_top_fileinfo to get size of saved fileinfo. memset( &mine_top_fileinfo, 0, sizeof(mine_top_fileinfo) ); if (cfseek( LoadFile, mine_start, SEEK_SET )) Error( "Error moving to top of file in gamemine.c" ); if (cfread( &mine_top_fileinfo, sizeof(mine_top_fileinfo), 1, LoadFile )!=1) Error( "Error reading mine_top_fileinfo in gamemine.c" ); if (mine_top_fileinfo.fileinfo_signature != 0x2884) return -1; // Check version number if (mine_top_fileinfo.fileinfo_version < COMPATIBLE_VERSION ) return -1; // Now, Read in the fileinfo if (cfseek( LoadFile, mine_start, SEEK_SET )) Error( "Error seeking to top of file in gamemine.c" ); if (cfread( &mine_fileinfo, mine_top_fileinfo.fileinfo_sizeof, 1, LoadFile )!=1) Error( "Error reading mine_fileinfo in gamemine.c" ); //===================== READ HEADER INFO ======================== // Set default values. mine_header.num_vertices = 0; mine_header.num_segments = 0; if (mine_fileinfo.header_offset > -1 ) { if (cfseek( LoadFile, mine_fileinfo.header_offset, SEEK_SET )) Error( "Error seeking to header_offset in gamemine.c" ); if (cfread( &mine_header, mine_fileinfo.header_size, 1, LoadFile )!=1) Error( "Error reading mine_header in gamemine.c" ); } //===================== READ EDITOR INFO ========================== // Set default values mine_editor.current_seg = 0; mine_editor.newsegment_offset = -1; // To be written mine_editor.newsegment_size = sizeof(segment); mine_editor.Curside = 0; mine_editor.Markedsegp = -1; mine_editor.Markedside = 0; if (mine_fileinfo.editor_offset > -1 ) { if (cfseek( LoadFile, mine_fileinfo.editor_offset, SEEK_SET )) Error( "Error seeking to editor_offset in gamemine.c" ); if (cfread( &mine_editor, mine_fileinfo.editor_size, 1, LoadFile )!=1) Error( "Error reading mine_editor in gamemine.c" ); } //===================== READ TEXTURE INFO ========================== if ( (mine_fileinfo.texture_offset > -1) && (mine_fileinfo.texture_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.texture_offset, SEEK_SET )) Error( "Error seeking to texture_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.texture_howmany; i++ ) { if (cfread( &old_tmap_list[i], mine_fileinfo.texture_sizeof, 1, LoadFile )!=1) Error( "Error reading old_tmap_list[i] in gamemine.c" ); } } //=============== GENERATE TEXTURE TRANSLATION TABLE =============== translate = 0; Assert (NumTextures < MAX_TEXTURES); { hashtable ht; hashtable_init( &ht, NumTextures ); // Remove all the file extensions in the textures list for (i=0;i<NumTextures;i++) { temptr = strchr(TmapInfo[i].filename, '.'); if (temptr) *temptr = '\0'; hashtable_insert( &ht, TmapInfo[i].filename, i ); } // For every texture, search through the texture list // to find a matching name. for (j=0;j<mine_fileinfo.texture_howmany;j++) { // Remove this texture name's extension temptr = strchr(old_tmap_list[j], '.'); if (temptr) *temptr = '\0'; tmap_xlate_table[j] = hashtable_search( &ht,old_tmap_list[j]); if (tmap_xlate_table[j] < 0 ) { //tmap_xlate_table[j] = 0; // mprintf( (0, "Couldn't find texture '%s'\n", old_tmap_list[j] )); ; } if (tmap_xlate_table[j] != j ) translate = 1; if (tmap_xlate_table[j] >= 0) tmap_times_used[tmap_xlate_table[j]]++; } { int count = 0; for (i=0; i<MAX_TEXTURES; i++ ) if (tmap_times_used[i]) count++; mprintf( (0, "This mine has %d unique textures in it (~%d KB)\n", count, (count*4096) /1024 )); } mprintf( (0, "Translate=%d\n", translate )); hashtable_free( &ht ); } //====================== READ VERTEX INFO ========================== // New check added to make sure we don't read in too many vertices. if ( mine_fileinfo.vertex_howmany > MAX_VERTICES ) { mprintf((0, "Num vertices exceeds maximum. Loading MAX %d vertices\n", MAX_VERTICES)); mine_fileinfo.vertex_howmany = MAX_VERTICES; } if ( (mine_fileinfo.vertex_offset > -1) && (mine_fileinfo.vertex_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.vertex_offset, SEEK_SET )) Error( "Error seeking to vertex_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.vertex_howmany; i++ ) { // Set the default values for this vertex Vertices[i].x = 1; Vertices[i].y = 1; Vertices[i].z = 1; if (cfread( &Vertices[i], mine_fileinfo.vertex_sizeof, 1, LoadFile )!=1) Error( "Error reading Vertices[i] in gamemine.c" ); } } //==================== READ SEGMENT INFO =========================== // New check added to make sure we don't read in too many segments. if ( mine_fileinfo.segment_howmany > MAX_SEGMENTS ) { mprintf((0, "Num segments exceeds maximum. Loading MAX %d segments\n", MAX_SEGMENTS)); mine_fileinfo.segment_howmany = MAX_SEGMENTS; } // [commented out by mk on 11/20/94 (weren't we supposed to hit final in October?) because it looks redundant. I think I'll test it now...] fuelcen_reset(); if ( (mine_fileinfo.segment_offset > -1) && (mine_fileinfo.segment_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.segment_offset,SEEK_SET )) Error( "Error seeking to segment_offset in gamemine.c" ); Highest_segment_index = mine_fileinfo.segment_howmany-1; for (i=0; i< mine_fileinfo.segment_howmany; i++ ) { segment v16_seg; // Set the default values for this segment (clear to zero ) //memset( &Segments[i], 0, sizeof(segment) ); if (mine_top_fileinfo.fileinfo_version >= 16) { Assert(mine_fileinfo.segment_sizeof == sizeof(v16_seg)); if (cfread( &v16_seg, mine_fileinfo.segment_sizeof, 1, LoadFile )!=1) Error( "Error reading segments in gamemine.c" ); } else Error("Invalid mine version"); Segments[i] = v16_seg; Segments[i].objects = -1; #ifdef EDITOR Segments[i].group = -1; #endif if (mine_top_fileinfo.fileinfo_version < 15) { //used old uvl ranges int sn,uvln; for (sn=0;sn<MAX_SIDES_PER_SEGMENT;sn++) for (uvln=0;uvln<4;uvln++) { Segments[i].sides[sn].uvls[uvln].u /= 64; Segments[i].sides[sn].uvls[uvln].v /= 64; Segments[i].sides[sn].uvls[uvln].l /= 32; } } fuelcen_activate( &Segments[i], Segments[i].special ); if (translate == 1) for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) { unsigned short orient; tmap_xlate = Segments[i].sides[j].tmap_num; Segments[i].sides[j].tmap_num = tmap_xlate_table[tmap_xlate]; if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG)) if (Segments[i].sides[j].tmap_num < 0) { mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j)); Int3(); Segments[i].sides[j].tmap_num = 0; } tmap_xlate = Segments[i].sides[j].tmap_num2 & 0x3FFF; orient = Segments[i].sides[j].tmap_num2 & (~0x3FFF); if (tmap_xlate != 0) { int xlated_tmap = tmap_xlate_table[tmap_xlate]; if ((WALL_IS_DOORWAY(&Segments[i],j) & WID_RENDER_FLAG)) if (xlated_tmap <= 0) { mprintf( (0, "Couldn't find texture '%s' for Segment %d, side %d\n", old_tmap_list[tmap_xlate],i,j)); Int3(); Segments[i].sides[j].tmap_num2 = 0; } Segments[i].sides[j].tmap_num2 = xlated_tmap | orient; } } } } //===================== READ NEWSEGMENT INFO ===================== #ifdef EDITOR { // Default segment created. vms_vector sizevec; med_create_new_segment(vm_vec_make(&sizevec,DEFAULT_X_SIZE,DEFAULT_Y_SIZE,DEFAULT_Z_SIZE)); // New_segment = Segments[0]; //memset( &New_segment, 0, sizeof(segment) ); } if (mine_editor.newsegment_offset > -1) { if (cfseek( LoadFile, mine_editor.newsegment_offset,SEEK_SET )) Error( "Error seeking to newsegment_offset in gamemine.c" ); if (cfread( &New_segment, mine_editor.newsegment_size,1,LoadFile )!=1) Error( "Error reading new_segment in gamemine.c" ); } if ( (mine_fileinfo.newseg_verts_offset > -1) && (mine_fileinfo.newseg_verts_howmany > 0)) { if (cfseek( LoadFile, mine_fileinfo.newseg_verts_offset, SEEK_SET )) Error( "Error seeking to newseg_verts_offset in gamemine.c" ); for (i=0; i< mine_fileinfo.newseg_verts_howmany; i++ ) { // Set the default values for this vertex Vertices[NEW_SEGMENT_VERTICES+i].x = 1; Vertices[NEW_SEGMENT_VERTICES+i].y = 1; Vertices[NEW_SEGMENT_VERTICES+i].z = 1; if (cfread( &Vertices[NEW_SEGMENT_VERTICES+i], mine_fileinfo.newseg_verts_sizeof,1,LoadFile )!=1) Error( "Error reading Vertices[NEW_SEGMENT_VERTICES+i] in gamemine.c" ); New_segment.verts[i] = NEW_SEGMENT_VERTICES+i; } } #endif //========================= UPDATE VARIABLES ====================== #ifdef EDITOR // Setting to Markedsegp to NULL ignores Curside and Markedside, which // we want to do when reading in an old file. Markedside = mine_editor.Markedside; Curside = mine_editor.Curside; for (i=0;i<10;i++) Groupside[i] = mine_editor.Groupside[i]; if ( mine_editor.current_seg != -1 ) Cursegp = mine_editor.current_seg + Segments; else Cursegp = NULL; if (mine_editor.Markedsegp != -1 ) Markedsegp = mine_editor.Markedsegp + Segments; else Markedsegp = NULL; num_groups = 0; current_group = -1; #endif Num_vertices = mine_fileinfo.vertex_howmany; Num_segments = mine_fileinfo.segment_howmany; Highest_vertex_index = Num_vertices-1; Highest_segment_index = Num_segments-1; reset_objects(1); //one object, the player #ifdef EDITOR Highest_vertex_index = MAX_SEGMENT_VERTICES-1; Highest_segment_index = MAX_SEGMENTS-1; set_vertex_counts(); Highest_vertex_index = Num_vertices-1; Highest_segment_index = Num_segments-1; warn_if_concave_segments(); #endif #ifdef EDITOR validate_segment_all(); #endif //create_local_segment_data(); //gamemine_find_textures(); if (mine_top_fileinfo.fileinfo_version < MINE_VERSION ) return 1; //old version else return 0; }
bool pilotfile::verify(const char *fname, int *rank, char *valid_language) { player t_plr; // set player ptr first thing p = &t_plr; filename = fname; if ( filename.size() == 4 ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("PLR => Unable to open '%s'!\n", filename.c_str())); return false; } unsigned int plr_id = cfread_uint(cfp); if (plr_id != PLR_FILE_ID) { mprintf(("PLR => Invalid header id for '%s'!\n", filename.c_str())); plr_close(); return false; } // version, now used version = cfread_ubyte(cfp); mprintf(("PLR => Verifying '%s' with version %d...\n", filename.c_str(), (int)version)); // the point of all this: read in the PLR contents while ( !(m_have_flags && m_have_info) && !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("PLR => Parsing: Flags...\n")); m_have_flags = true; plr_read_flags(); break; // now reading the Info section to get the campaign // and be able to lookup the campaign rank case Section::Info: mprintf(("PLR => Parsing: Info...\n")); m_have_info = true; plr_read_info(); break; default: break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("PLR => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("PLR => ERROR: %s\n", err)); plr_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("PLR => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, offset_pos, CF_SEEK_CUR); } } if (valid_language) { strncpy(valid_language, p->language, sizeof(p->language)); } // need to cleanup early to ensure everything is OK for use in the CSG next // also means we can't use *p from now on, use t_plr instead for a few vars plr_close(); if (rank) { // maybe get the rank from the CSG if ( !(Game_mode & GM_MULTIPLAYER) ) { // build the csg filename // since filename/fname was validated above, perform less safety checks here filename = fname; filename = filename.replace(filename.find_last_of('.')+1,filename.npos, t_plr.current_campaign); filename.append(".csg"); if (!this->get_csg_rank(rank)) { // if we failed to get the csg rank, default to multi rank *rank = t_plr.stats.rank; } } else { // if the CSG isn't valid, or for multi, use this rank *rank = t_plr.stats.rank; } } mprintf(("PLR => Verifying complete!\n")); return true; }
int pcx_read_bitmap_32(char *real_filename, ubyte *org_data ) { PCXHeader header; CFILE * PCXfile; ubyte data=0; int row, col, count; int buffer_pos; char filename[MAX_FILENAME_LEN]; ubyte palette[768]; strcpy( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat( filename, ".pcx" ); PCXfile = cfopen( filename , "rb" ); if ( !PCXfile ){ return PCX_ERROR_OPENING; } // read 128 char PCX header if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { cfclose( PCXfile ); return PCX_ERROR_OPENING; } // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { cfclose( PCXfile ); return PCX_ERROR_OPENING; } // Find the size of the image int src_xsize = header.Xmax - header.Xmin + 1; int src_ysize = header.Ymax - header.Ymin + 1; // Read the extended palette at the end of PCX file // Read in a character which should be 12 to be extended palette file cfseek( PCXfile, -768, CF_SEEK_END ); cfread( palette, 3, 256, PCXfile ); cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET ); int buffer_size = 1024; ubyte buffer[1024]; buffer_pos = 0; buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); count = 0; typedef struct {ubyte b,g,r,a;} COLOR32; for (row=0; row < src_ysize;row++) { COLOR32 *pixdata = (COLOR32 *) org_data; for (col=0; col < header.BytesPerLine;col++) { if ( count == 0 ) { data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } if ((data & 0xC0) == 0xC0) { count = data & 0x3F; data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } } else { count = 1; } } // stuff the pixel if ( col < src_xsize ){ if((0 == (int)palette[data*3]) && (255 == (int)palette[data*3+1]) && (0 == (int)palette[data*3+2])){ pixdata->r = pixdata->b = pixdata->g = pixdata->a = 0; } else { // stuff the 24 bit value pixdata->r = palette[data*3]; pixdata->g = palette[data*3 + 1]; pixdata->b = palette[data*3 + 2]; pixdata->a = 255; } pixdata++; } count--; } org_data += (src_xsize * 4); } cfclose(PCXfile); return PCX_ERROR_NONE; }
bool pilotfile::load_player(const char *callsign, player *_p) { // if we're a standalone server in multiplayer, just fill in some bogus values // since we don't have a pilot file if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_STANDALONE_SERVER) ) { Player->insignia_texture = -1; strcpy_s(Player->callsign, NOX("Standalone")); strcpy_s(Player->short_callsign, NOX("Standalone")); return true; } // set player ptr first thing p = _p; if ( !p ) { Assert( (Player_num >= 0) && (Player_num < MAX_PLAYERS) ); p = &Players[Player_num]; } filename = callsign; filename += ".plr"; if ( filename.size() == 4 ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("PLR => Unable to open '%s' for reading!\n", filename.c_str())); return false; } unsigned int plr_id = cfread_uint(cfp); if (plr_id != PLR_FILE_ID) { mprintf(("PLR => Invalid header id for '%s'!\n", filename.c_str())); plr_close(); return false; } // version, should be able to just ignore it version = cfread_ubyte(cfp); mprintf(("PLR => Loading '%s' with version %d...\n", filename.c_str(), version)); plr_reset_data(); // the point of all this: read in the PLR contents while ( !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("PLR => Parsing: Flags...\n")); m_have_flags = true; plr_read_flags(); break; case Section::Info: mprintf(("PLR => Parsing: Info...\n")); m_have_info = true; plr_read_info(); break; case Section::Variables: mprintf(("PLR => Parsing: Variables...\n")); plr_read_variables(); break; case Section::HUD: mprintf(("PLR => Parsing: HUD...\n")); plr_read_hud(); break; case Section::Scoring: mprintf(("PLR => Parsing: Scoring...\n")); plr_read_stats(); break; case Section::ScoringMulti: mprintf(("PLR => Parsing: ScoringMulti...\n")); plr_read_stats_multi(); break; case Section::Multiplayer: mprintf(("PLR => Parsing: Multiplayer...\n")); plr_read_multiplayer(); break; case Section::Controls: mprintf(("PLR => Parsing: Controls...\n")); plr_read_controls(); break; case Section::Settings: mprintf(("PLR => Parsing: Settings...\n")); plr_read_settings(); break; default: mprintf(("PLR => Skipping unknown section 0x%04x!\n", section_id)); break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("PLR => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("PLR => ERROR: %s\n", err)); plr_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { cfseek(cfp, offset_pos, CF_SEEK_CUR); } } // restore the callsign into the Player structure strcpy_s(p->callsign, callsign); // restore the truncated callsign into Player structure pilot_set_short_callsign(p, SHORT_CALLSIGN_PIXEL_W); player_set_squad_bitmap(p, p->m_squad_filename, true); hud_squadmsg_save_keys(); // set last pilot os_config_write_string(NULL, "LastPlayer", (char*)callsign); mprintf(("PLR => Loading complete!\n")); // cleanup and return plr_close(); return true; }
int piggy_init() { int sbytes = 0; char temp_name_read[16]; char temp_name[16]; grs_bitmap temp_bitmap; digi_sound temp_sound; DiskBitmapHeader bmh; DiskSoundHeader sndh; int header_size, N_bitmaps, N_sounds; int i,size, length; char * filename; int read_sounds = 1; int Pigdata_start; hashtable_init( &AllBitmapsNames, MAX_BITMAP_FILES ); // hashtable_init( &AllDigiSndNames, MAX_SOUND_FILES ); if (GameBitmaps == NULL) { GameBitmaps = (grs_bitmap *)mymalloc(sizeof(grs_bitmap) * MAX_BITMAP_FILES); if (GameBitmaps == NULL) Error("Cannot allocate space for game bitmaps in piggy.c"); } if (AllBitmaps == NULL) { AllBitmaps = (BitmapFile *)mymalloc(sizeof(BitmapFile) * MAX_BITMAP_FILES); if (AllBitmaps == NULL) Error("Cannot allocate space for bitmap filenames in piggy.c"); } #if 0 if (AllSounds == NULL) { AllSounds = (SoundFile *)mymalloc(sizeof(SoundFile) * MAX_SOUND_FILES); if (AllSounds == NULL) Error("Cannot allocate space for sound filenames in piggy.c"); } if ( FindArg( "-nosound" ) || (digi_driver_board<1) ) { read_sounds = 0; mprintf(( 0, "Not loading sound data!!!!!\n" )); } for (i=0; i<MAX_SOUND_FILES; i++ ) { GameSounds[i].length = 0; GameSounds[i].data = NULL; SoundOffset[i] = 0; } #endif for (i=0; i<MAX_BITMAP_FILES; i++ ) GameBitmapXlat[i] = i; if ( !bogus_bitmap_initialized ) { int i; ubyte c; bogus_bitmap_initialized = 1; memset( &bogus_bitmap, 0, sizeof(grs_bitmap) ); bogus_bitmap.bm_w = bogus_bitmap.bm_h = bogus_bitmap.bm_rowsize = 64; bogus_bitmap.bm_data = bogus_data; c = gr_find_closest_color( 0, 0, 63 ); for (i=0; i<4096; i++ ) bogus_data[i] = c; c = gr_find_closest_color( 63, 0, 0 ); // Make a big red X ! for (i=0; i<64; i++ ) { bogus_data[i*64+i] = c; bogus_data[i*64+(63-i)] = c; } piggy_register_bitmap( &bogus_bitmap, "bogus", 1 ); bogus_sound.length = 64*64; bogus_sound.data = bogus_data; GameBitmapOffset[0] = 0; } filename = ":Data:DESCENT.PIG"; if ( FindArg( "-bigpig" )) BigPig = 1; if ( FindArg( "-lowmem" )) piggy_low_memory = 1; if ( FindArg( "-nolowmem" )) piggy_low_memory = 0; if (use_alt_textures) piggy_low_memory = 1; //MWA if (piggy_low_memory) //MWA digi_lomem = 1; if ( (i=FindArg( "-piggy" )) ) { filename = Args[i+1]; mprintf( (0, "Using alternate pigfile, '%s'\n", filename )); } Piggy_fp = cfopen( filename, "rb" ); if (Piggy_fp==NULL) return 0; Pigdata_start = read_int_swap(Piggy_fp); #ifdef EDITOR if ( FindArg("-nobm") ) #endif { bm_read_all( Piggy_fp ); // Note connection to above if!!! for (i = 0; i < MAX_BITMAP_FILES; i++) GameBitmapXlat[i] = read_short_swap(Piggy_fp); digi_load_sounds(); } cfseek( Piggy_fp, Pigdata_start, SEEK_SET ); size = cfilelength(Piggy_fp) - Pigdata_start; length = size; mprintf( (0, "\nReading data (%d KB) ", size/1024 )); N_bitmaps = read_int_swap(Piggy_fp); size -= sizeof(int); N_sounds = read_int_swap(Piggy_fp); size -= sizeof(int); // header_size = (N_bitmaps*sizeof(DiskBitmapHeader)) + (N_sounds*sizeof(DiskSoundHeader)); header_size = ((N_bitmaps*17) + (N_sounds*20)); gr_set_curfont( Gamefonts[GFONT_SMALL] ); gr_set_fontcolor(gr_find_closest_color_current( 20, 20, 20 ),-1 ); gr_printf( 0x8000, grd_curcanv->cv_bitmap.bm_h - 25, "%s...", TXT_LOADING_DATA ); bitblt_to_screen(); // put a couple of event loop calls here. This should take care of TM driver!!! process_one_event(); process_one_event(); process_one_event(); process_one_event(); for (i=0; i<N_bitmaps; i++ ) { cfread(bmh.name, 8, 1, Piggy_fp); bmh.dflags = read_byte(Piggy_fp); bmh.width = read_byte(Piggy_fp); bmh.height = read_byte(Piggy_fp); bmh.flags = read_byte(Piggy_fp); bmh.avg_color = read_byte(Piggy_fp); bmh.offset = read_int_swap(Piggy_fp); //size -= sizeof(DiskBitmapHeader); memcpy( temp_name_read, bmh.name, 8 ); temp_name_read[8] = 0; if ( bmh.dflags & DBM_FLAG_ABM ) sprintf( temp_name, "%s#%d", temp_name_read, bmh.dflags & 63 ); else strcpy( temp_name, temp_name_read ); memset( &temp_bitmap, 0, sizeof(grs_bitmap) ); if ( bmh.dflags & DBM_FLAG_LARGE ) temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width+256; else temp_bitmap.bm_w = temp_bitmap.bm_rowsize = bmh.width; temp_bitmap.bm_h = bmh.height; temp_bitmap.bm_flags = BM_FLAG_PAGED_OUT; temp_bitmap.avg_color = bmh.avg_color; temp_bitmap.bm_data = Piggy_bitmap_cache_data; // HACK HACK HACK!!!!! if (!strnicmp(bmh.name, "cockpit", 7) || !strnicmp(bmh.name, "status", 6) || !strnicmp(bmh.name, "rearview", 8)) { temp_bitmap.bm_w = temp_bitmap.bm_rowsize = 640; } if (!strnicmp(bmh.name, "cockpit", 7) || !strnicmp(bmh.name, "rearview", 8)) temp_bitmap.bm_h = 480; GameBitmapFlags[i+1] = 0; if ( bmh.flags & BM_FLAG_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_TRANSPARENT; if ( bmh.flags & BM_FLAG_SUPER_TRANSPARENT ) GameBitmapFlags[i+1] |= BM_FLAG_SUPER_TRANSPARENT; if ( bmh.flags & BM_FLAG_NO_LIGHTING ) GameBitmapFlags[i+1] |= BM_FLAG_NO_LIGHTING; if ( bmh.flags & BM_FLAG_RLE ) GameBitmapFlags[i+1] |= BM_FLAG_RLE; GameBitmapOffset[i+1] = bmh.offset + header_size + (sizeof(int)*2) + Pigdata_start; Assert( (i+1) == Num_bitmap_files ); piggy_register_bitmap( &temp_bitmap, temp_name, 1 ); } #if 0 for (i=0; i<N_sounds; i++ ) { cfread(sndh.name, 8, 1, Piggy_fp); sndh.length = read_int_swap(Piggy_fp); sndh.data_length = read_int_swap(Piggy_fp); sndh.offset = read_int_swap(Piggy_fp); //size -= sizeof(DiskSoundHeader); temp_sound.length = sndh.length; temp_sound.data = (ubyte *)(sndh.offset + header_size + (sizeof(int)*2)+Pigdata_start); SoundOffset[Num_sound_files] = sndh.offset + header_size + (sizeof(int)*2)+Pigdata_start; memcpy( temp_name_read, sndh.name, 8 ); temp_name_read[8] = 0; piggy_register_sound( &temp_sound, temp_name_read, 1 ); sbytes += sndh.length; //mprintf(( 0, "%d bytes of sound\n", sbytes )); } SoundBits = mymalloc( sbytes + 16 ); if ( SoundBits == NULL ) Error( "Not enough memory to load DESCENT.PIG sounds\n" ); #endif #ifdef EDITOR Piggy_bitmap_cache_size = size - header_size - sbytes + 16; Assert( Piggy_bitmap_cache_size > 0 ); #else if (!piggy_low_memory) Piggy_bitmap_cache_size = PIGGY_BUFFER_SIZE; else Piggy_bitmap_cache_size = LOW_PIGGY_BUFFER_SIZE; #endif BitmapBits = mymalloc( Piggy_bitmap_cache_size ); if ( BitmapBits == NULL ) Error( "Not enough memory to load DESCENT.PIG bitmaps\n" ); Piggy_bitmap_cache_data = BitmapBits; Piggy_bitmap_cache_next = 0; mprintf(( 0, "\nBitmaps: %d KB Sounds: %d KB\n", Piggy_bitmap_cache_size/1024, sbytes/1024 )); atexit(piggy_close_file); // mprintf( (0, "<<<<Paging in all piggy bitmaps...>>>>>" )); // for (i=0; i < Num_bitmap_files; i++ ) { // bitmap_index bi; // bi.index = i; // PIGGY_PAGE_IN( bi ); // } // mprintf( (0, "\n (USed %d / %d KB)\n", Piggy_bitmap_cache_next/1024, (size - header_size - sbytes + 16)/1024 )); // key_getch(); return 0; }
bool pilotfile::verify(const char *fname, int *rank) { player t_plr; // set player ptr first thing p = &t_plr; filename = fname; if ( filename.size() == 4 ) { mprintf(("PLR => Invalid filename '%s'!\n", filename.c_str())); return false; } cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("PLR => Unable to open '%s'!\n", filename.c_str())); return false; } unsigned int plr_id = cfread_uint(cfp); if (plr_id != PLR_FILE_ID) { mprintf(("PLR => Invalid header id for '%s'!\n", filename.c_str())); plr_close(); return false; } // version, should be able to just ignore it ubyte plr_ver = cfread_ubyte(cfp); mprintf(("PLR => Verifying '%s' with version %d...\n", filename.c_str(), (int)plr_ver)); // the point of all this: read in the PLR contents while ( !m_have_flags && !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("PLR => Parsing: Flags...\n")); m_have_flags = true; plr_read_flags(); break; default: break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("PLR => (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("PLR => ERROR: %s\n", err)); plr_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("PLR => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, offset_pos, CF_SEEK_CUR); } } if (rank) { *rank = p->stats.rank; } mprintf(("PLR => Verifying complete!\n")); // cleanup and return plr_close(); return true; }
void piggy_bitmap_page_in( bitmap_index bitmap ) { grs_bitmap * bmp; int i,org_i,temp; char buf[256]; ubyte *src; i = bitmap.index; Assert( i >= 0 ); Assert( i < MAX_BITMAP_FILES ); Assert( i < Num_bitmap_files ); Assert( Piggy_bitmap_cache_size > 0 ); if ( GameBitmapOffset[i] == 0 ) return; // A read-from-disk bitmap!!! if ( piggy_low_memory ) { org_i = i; i = GameBitmapXlat[i]; // Xlat for low-memory settings! } bmp = &GameBitmaps[i]; if ( bmp->bm_flags & BM_FLAG_PAGED_OUT ) { stop_time(); ReDoIt: descent_critical_error = 0; cfseek( Piggy_fp, GameBitmapOffset[i], SEEK_SET ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } bmp->bm_data = &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next]; bmp->bm_flags = GameBitmapFlags[i]; if ( bmp->bm_flags & BM_FLAG_RLE ) { int zsize = 0; descent_critical_error = 0; zsize = read_int_swap(Piggy_fp); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } // GET JOHN NOW IF YOU GET THIS ASSERT!!! Assert( Piggy_bitmap_cache_next+zsize < Piggy_bitmap_cache_size ); if ( Piggy_bitmap_cache_next+zsize >= Piggy_bitmap_cache_size ) { piggy_bitmap_page_out_all(); goto ReDoIt; } memcpy( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], &zsize, sizeof(int) ); Piggy_bitmap_cache_next += sizeof(int); descent_critical_error = 0; temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, zsize-4, Piggy_fp ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } Piggy_bitmap_cache_next += zsize-4; } else { // GET JOHN NOW IF YOU GET THIS ASSERT!!! Assert( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) < Piggy_bitmap_cache_size ); if ( Piggy_bitmap_cache_next+(bmp->bm_h*bmp->bm_w) >= Piggy_bitmap_cache_size ) { piggy_bitmap_page_out_all(); goto ReDoIt; } descent_critical_error = 0; temp = cfread( &Piggy_bitmap_cache_data[Piggy_bitmap_cache_next], 1, bmp->bm_h*bmp->bm_w, Piggy_fp ); if ( descent_critical_error ) { piggy_critical_error(); goto ReDoIt; } Piggy_bitmap_cache_next+=bmp->bm_h*bmp->bm_w; #if 0 temp = bmp->bm_h*bmp->bm_w; src = (ubyte *)bmp->bm_data; for (i = 0; i < temp; i++) { if (*src == 0) *src = 255; else if (*src == 255) *src = 0; src++; } #endif } start_time(); } if ( piggy_low_memory ) { if ( org_i != i ) GameBitmaps[org_i] = GameBitmaps[i]; } }
// #define GET_BUF() do { buffer = &Pcx_load[Pcx_load_offset]; if(Pcx_load_offset + buffer_size > Pcx_load_size) { buffer_size = Pcx_load_size - Pcx_load_offset; } } while(0); int pcx_read_bitmap_8bpp( char * real_filename, ubyte *org_data, ubyte *palette ) { PCXHeader header; CFILE * PCXfile; int row, col, count, xsize, ysize; ubyte data=0; int buffer_size, buffer_pos; ubyte buffer[1024]; ubyte *pixdata; char filename[MAX_FILENAME_LEN]; strcpy( filename, real_filename ); char *p = strchr( filename, '.' ); if ( p ) *p = 0; strcat( filename, ".pcx" ); PCXfile = cfopen( filename , "rb" ); if ( !PCXfile ) return PCX_ERROR_OPENING; // read 128 char PCX header if (cfread( &header, sizeof(PCXHeader), 1, PCXfile )!=1) { cfclose( PCXfile ); return PCX_ERROR_NO_HEADER; } header.Xmin = INTEL_SHORT( header.Xmin ); header.Ymin = INTEL_SHORT( header.Ymin ); header.Xmax = INTEL_SHORT( header.Xmax ); header.Ymax = INTEL_SHORT( header.Ymax ); header.Hdpi = INTEL_SHORT( header.Hdpi ); header.Vdpi = INTEL_SHORT( header.Vdpi ); header.BytesPerLine = INTEL_SHORT( header.BytesPerLine ); // Is it a 256 color PCX file? if ((header.Manufacturer != 10)||(header.Encoding != 1)||(header.Nplanes != 1)||(header.BitsPerPixel != 8)||(header.Version != 5)) { cfclose( PCXfile ); return PCX_ERROR_WRONG_VERSION; } // Find the size of the image xsize = header.Xmax - header.Xmin + 1; ysize = header.Ymax - header.Ymin + 1; // Read the extended palette at the end of PCX file // Read in a character which should be 12 to be extended palette file cfseek( PCXfile, -768, CF_SEEK_END ); cfread( palette, 3, 256, PCXfile ); for ( int i=0; i<256; i++ ){ //tigital palette[i] = INTEL_INT( palette[i] ); } cfseek( PCXfile, sizeof(PCXHeader), CF_SEEK_SET ); buffer_size = 1024; buffer_pos = 0; // Assert( buffer_size == 1024 ); // AL: removed to avoid optimized warning 'unreachable code' buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); count = 0; for (row=0; row<ysize;row++) { pixdata = org_data; for (col=0; col<header.BytesPerLine;col++) { if ( count == 0 ) { data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } if ((data & 0xC0) == 0xC0) { count = data & 0x3F; data = buffer[buffer_pos++]; if ( buffer_pos == buffer_size ) { buffer_size = cfread( buffer, 1, buffer_size, PCXfile ); Assert( buffer_size > 0 ); buffer_pos = 0; } } else { count = 1; } } if ( col < xsize ) *pixdata++ = data; count--; } org_data += xsize; } cfclose(PCXfile); return PCX_ERROR_NONE; }
bool pilotfile::load_savefile(const char *campaign) { char base[_MAX_FNAME] = { '\0' }; std::ostringstream buf; if (Game_mode & GM_MULTIPLAYER) { return false; } if ( (campaign == NULL) || !strlen(campaign) ) { return false; } // set player ptr first thing Assert( (Player_num >= 0) && (Player_num < MAX_PLAYERS) ); p = &Players[Player_num]; // build up filename for the savefile... _splitpath((char*)campaign, NULL, NULL, base, NULL); buf << p->callsign << "." << base << ".csg"; filename = buf.str().c_str(); // if campaign file doesn't exist, abort so we don't load irrelevant data buf.str(std::string()); buf << base << FS_CAMPAIGN_FILE_EXT; if ( !cf_exists_full((char*)buf.str().c_str(), CF_TYPE_MISSIONS) ) { mprintf(("CSG => Unable to find campaign file '%s'!\n", buf.str().c_str())); return false; } // we need to reset this early, in case open fails and we need to create m_data_invalid = false; // open it, hopefully... cfp = cfopen((char*)filename.c_str(), "rb", CFILE_NORMAL, CF_TYPE_PLAYERS); if ( !cfp ) { mprintf(("CSG => Unable to open '%s' for reading!\n", filename.c_str())); return false; } unsigned int csg_id = cfread_uint(cfp); if (csg_id != CSG_FILE_ID) { mprintf(("CSG => Invalid header id for '%s'!\n", filename.c_str())); csg_close(); return false; } // version, now used csg_ver = cfread_ubyte(cfp); mprintf(("CSG => Loading '%s' with version %d...\n", filename.c_str(), (int)csg_ver)); csg_reset_data(); // the point of all this: read in the CSG contents while ( !cfeof(cfp) ) { ushort section_id = cfread_ushort(cfp); uint section_size = cfread_uint(cfp); size_t start_pos = cftell(cfp); // safety, to help protect against long reads cf_set_max_read_len(cfp, section_size); try { switch (section_id) { case Section::Flags: mprintf(("CSG => Parsing: Flags...\n")); m_have_flags = true; csg_read_flags(); break; case Section::Info: mprintf(("CSG => Parsing: Info...\n")); m_have_info = true; csg_read_info(); break; case Section::Variables: mprintf(("CSG => Parsing: Variables...\n")); csg_read_variables(); break; case Section::HUD: mprintf(("CSG => Parsing: HUD...\n")); csg_read_hud(); break; case Section::RedAlert: mprintf(("CSG => Parsing: RedAlert...\n")); csg_read_redalert(); break; case Section::Scoring: mprintf(("CSG => Parsing: Scoring...\n")); csg_read_stats(); break; case Section::Loadout: mprintf(("CSG => Parsing: Loadout...\n")); csg_read_loadout(); break; case Section::Techroom: mprintf(("CSG => Parsing: Techroom...\n")); csg_read_techroom(); break; case Section::Missions: mprintf(("CSG => Parsing: Missions...\n")); csg_read_missions(); break; case Section::Settings: mprintf(("CSG => Parsing: Settings...\n")); csg_read_settings(); break; case Section::Controls: mprintf(("CSG => Parsing: Controls...\n")); csg_read_controls(); break; case Section::Cutscenes: mprintf(("CSG => Parsing: Cutscenes...\n")); csg_read_cutscenes(); break; case Section::LastMissions: mprintf(("CSG => Parsing: Last Missions...\n")); csg_read_lastmissions(); break; default: mprintf(("CSG => Skipping unknown section 0x%04x!\n", section_id)); break; } } catch (cfile::max_read_length &msg) { // read to max section size, move to next section, discarding // extra/unknown data mprintf(("CSG => Warning: (0x%04x) %s\n", section_id, msg.what())); } catch (const char *err) { mprintf(("CSG => ERROR: %s\n", err)); csg_close(); return false; } // reset safety catch cf_set_max_read_len(cfp, 0); // skip to next section (if not already there) size_t offset_pos = (start_pos + section_size) - cftell(cfp); if (offset_pos) { mprintf(("CSG => Warning: (0x%04x) Short read, information may have been lost!\n", section_id)); cfseek(cfp, (int)offset_pos, CF_SEEK_CUR); } } // if the campaign (for whatever reason) doesn't have a squad image, use the multi one if (p->s_squad_filename[0] == '\0') { strcpy_s(p->s_squad_filename, p->m_squad_filename); } player_set_squad_bitmap(p, p->s_squad_filename, false); mprintf(("CSG => Loading complete!\n")); // cleanup and return csg_close(); return true; }
int ogg_cfseek(void* cfile, ogg_int64_t offset, int where) { return cfseek((CFILE*)cfile, (int)offset, where); }
hmp_file *hmp_open(const char *filename) { int i; char buf[256]; int32_t data; CFILE *fp; hmp_file *hmp; int num_tracks; unsigned char *p; if (!(fp = cfopen((char *)filename, "rb"))) return NULL; hmp = malloc(sizeof(hmp_file)); if (!hmp) { cfclose(fp); return NULL; } memset(hmp, 0, sizeof(*hmp)); if ((cfread(buf, 1, 8, fp) != 8) || (memcmp(buf, "HMIMIDIP", 8))) goto err; if (cfseek(fp, 0x30, SEEK_SET)) goto err; if (cfread(&num_tracks, 4, 1, fp) != 1) goto err; if ((num_tracks < 1) || (num_tracks > HMP_TRACKS)) goto err; hmp->num_trks = num_tracks; hmp->tempo = 120; if (cfseek(fp, 0x308, SEEK_SET)) goto err; for (i = 0; i < num_tracks; i++) { if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(&data, 4, 1, fp) != 1)) goto err; data -= 12; #if 0 if (i == 0) /* track 0: reserve length for tempo */ data += sizeof(hmp_tempo); #endif hmp->trks[i].len = data; if (!(p = hmp->trks[i].data = malloc(data))) goto err; #if 0 if (i == 0) { /* track 0: add tempo */ memcpy(p, hmp_tempo, sizeof(hmp_tempo)); p += sizeof(hmp_tempo); data -= sizeof(hmp_tempo); } #endif /* finally, read track data */ if ((cfseek(fp, 4, SEEK_CUR)) || (cfread(p, data, 1, fp) != 1)) goto err; } cfclose(fp); return hmp; err: cfclose(fp); hmp_close(hmp); return NULL; }