void rewind_recording( void) { if(replay.game_is_being_recorded) { /* This is unnecessary, because it is called from reset_player_queues, */ /* which is always called from revert_game */ /* FilmFile.SetLength(sizeof(recording_header)); FilmFile.SetPosition(sizeof(recording_header)); */ // Alternative that does not use "SetLength", but instead creates and re-creates the file. FilmFile.SetPosition(0); byte Header[SIZEOF_recording_header]; FilmFile.Read(SIZEOF_recording_header,Header); FilmFile.Close(); FilmFileSpec.Delete(); FilmFileSpec.Create(_typecode_film); FilmFileSpec.Open(FilmFile,true); FilmFile.Write(SIZEOF_recording_header,Header); // Use the packed length here!!! replay.header.length= SIZEOF_recording_header; } }
void stop_recording( void) { if (replay.game_is_being_recorded) { replay.game_is_being_recorded = false; short player_index; int32 total_length; assert(replay.valid); for (player_index= 0; player_index<dynamic_world->player_count; player_index++) { save_recording_queue_chunk(player_index); } /* Rewrite the header, since it has the new length */ FilmFile.SetPosition(0); byte Header[SIZEOF_recording_header]; pack_recording_header(Header,&replay.header,1); // ZZZ: removing code that does stuff from assert() argument. BUT... // should we really be asserting on this anyway? I mean, the write could fail // in 'normal operation' too, not just when we screwed something up in writing the program? bool successfulWrite = FilmFile.Write(SIZEOF_recording_header,Header); assert(successfulWrite); FilmFile.GetLength(total_length); assert(total_length==replay.header.length); FilmFile.Close(); } replay.valid= false; }
bool SkipChunk(OpenedFile& OFile, ChunkHeaderData& ChunkHeader) { logTrace2("Skipping chunk 0x%04hx size %u",ChunkHeader.ID,ChunkHeader.Size); int32 DataSize = ChunkHeader.Size - SIZEOF_ChunkHeaderData; int32 Location = 0; OFile.GetPosition(Location); if (!OFile.SetPosition(Location + DataSize)) return false; return true; }
// Determine file type Typecode FileSpecifier::GetType() { // if there's an extension, assume it's correct const char *extension = strrchr(GetPath(), '.'); if (extension) { extension_mapping *mapping = extensions; while (mapping->extension) { if (( mapping->case_sensitive && (strcmp(extension + 1, mapping->extension) == 0)) || (!mapping->case_sensitive && (strcasecmp(extension + 1, mapping->extension) == 0))) { return mapping->typecode; } ++mapping; } } // Open file OpenedFile f; if (!Open(f)) return _typecode_unknown; SDL_RWops *p = f.GetRWops(); int32 file_length = 0; f.GetLength(file_length); // Check for Sounds file { f.SetPosition(0); uint32 version = SDL_ReadBE32(p); uint32 tag = SDL_ReadBE32(p); if ((version == 0 || version == 1) && tag == FOUR_CHARS_TO_INT('s', 'n', 'd', '2')) return _typecode_sounds; } // Check for Map/Physics file { f.SetPosition(0); int version = SDL_ReadBE16(p); int data_version = SDL_ReadBE16(p); if ((version == 0 || version == 1 || version == 2 || version == 4) && (data_version == 0 || data_version == 1 || data_version == 2)) { SDL_RWseek(p, 68, SEEK_CUR); int32 directory_offset = SDL_ReadBE32(p); if (directory_offset >= file_length) goto not_map; f.SetPosition(128); uint32 tag = SDL_ReadBE32(p); // ghs: I do not believe this list is comprehensive // I think it's just what we've seen so far? switch (tag) { case LINE_TAG: case POINT_TAG: case SIDE_TAG: return _typecode_scenario; break; case MONSTER_PHYSICS_TAG: return _typecode_physics; break; } } not_map: ; } // Check for Shapes file { f.SetPosition(0); for (int i=0; i<32; i++) { uint32 status_flags = SDL_ReadBE32(p); int32 offset = SDL_ReadBE32(p); int32 length = SDL_ReadBE32(p); int32 offset16 = SDL_ReadBE32(p); int32 length16 = SDL_ReadBE32(p); if (status_flags != 0 || (offset != NONE && (offset >= file_length || offset + length > file_length)) || (offset16 != NONE && (offset16 >= file_length || offset16 + length16 > file_length))) goto not_shapes; SDL_RWseek(p, 12, SEEK_CUR); } return _typecode_shapes; not_shapes: ; } // Not identified return _typecode_unknown; }