void check_recording_replaying( void) { short player_index, queue_size; if (replay.game_is_being_recorded) { boolean enough_data_to_save= TRUE; // it's time to save the queues if all of them have >= RECORD_CHUNK_SIZE flags in them. for (player_index= 0; enough_data_to_save && player_index<dynamic_world->player_count; player_index++) { queue_size= get_recording_queue_size(player_index); if (queue_size < RECORD_CHUNK_SIZE) enough_data_to_save= FALSE; } if(enough_data_to_save) { boolean success; unsigned long freespace; FileDesc recording_file; get_recording_filedesc(&recording_file); success= get_freespace_on_disk(&recording_file, &freespace); if (success && freespace>(RECORD_CHUNK_SIZE*sizeof(short)*sizeof(long)*dynamic_world->player_count)) { for (player_index= 0; player_index<dynamic_world->player_count; player_index++) { save_recording_queue_chunk(player_index); } } } } else if (replay.game_is_being_replayed) { boolean load_new_data= TRUE; // it's time to refill the requeues if they all have < RECORD_CHUNK_SIZE flags in them. for (player_index= 0; load_new_data && player_index<dynamic_world->player_count; player_index++) { queue_size= get_recording_queue_size(player_index); if(queue_size>= RECORD_CHUNK_SIZE) load_new_data= FALSE; } if(load_new_data) { // at this point, weÕve determined that the queues are sufficently empty, so // weÕll fill Õem up. read_recording_queue_chunks(); } } return; }
void check_recording_replaying( void) { short player_index, queue_size; if (replay.game_is_being_recorded) { bool enough_data_to_save= true; // it's time to save the queues if all of them have >= RECORD_CHUNK_SIZE flags in them. for (player_index= 0; enough_data_to_save && player_index<dynamic_world->player_count; player_index++) { queue_size= get_recording_queue_size(player_index); if (queue_size < RECORD_CHUNK_SIZE) enough_data_to_save= false; } if(enough_data_to_save) { bool success; uint32 freespace = 0; FileSpecifier FilmFile_Check; get_recording_filedesc(FilmFile_Check); success= FilmFile_Check.GetFreeSpace(freespace); if (success && freespace>(RECORD_CHUNK_SIZE*sizeof(int16)*sizeof(uint32)*dynamic_world->player_count)) { for (player_index= 0; player_index<dynamic_world->player_count; player_index++) { save_recording_queue_chunk(player_index); } } } } else if (replay.game_is_being_replayed) { bool load_new_data= true; // it's time to refill the requeues if they all have < RECORD_CHUNK_SIZE flags in them. for (player_index= 0; load_new_data && player_index<dynamic_world->player_count; player_index++) { queue_size= get_recording_queue_size(player_index); if(queue_size>= RECORD_CHUNK_SIZE) load_new_data= false; } if(load_new_data) { // at this point, we've determined that the queues are sufficently empty, so // we'll fill 'em up. read_recording_queue_chunks(); } } }
/********************************************************************************************* * * Function: pull_flags_from_recording * Purpose: remove one flag from each queue from the recording buffer. * Returns: TRUE if it pulled the flags, FALSE if it didn't * *********************************************************************************************/ static boolean pull_flags_from_recording( short count) { short player_index; boolean success= TRUE; // first check that we can pull something from each playerÕs queue // (at the beginning of the game, we wonÕt be able to) // i'm not sure that i really need to do this check. oh well. for (player_index = 0; success && player_index<dynamic_world->player_count; player_index++) { if(get_recording_queue_size(player_index)==0) success= FALSE; } if(success) { for (player_index = 0; player_index < dynamic_world->player_count; player_index++) { short index; ActionQueue *queue; queue= get_player_recording_queue(player_index); for (index= 0; index<count; index++) { if (queue->read_index != queue->write_index) { #ifdef DEBUG_REPLAY debug_stream_of_flags(*(queue->buffer+queue->read_index), player_index); #endif queue_action_flags(player_index, queue->buffer+queue->read_index, 1); INCREMENT_QUEUE_COUNTER(queue->read_index); } else { dprintf("Dropping flag?"); } } } } return success; }
/********************************************************************************************* * * Function: save_recording_queue_chunk * Purpose: saves one chunk of the queue to the recording file, using run-length encoding. * *********************************************************************************************/ void save_recording_queue_chunk( short player_index) { long *location; long last_flag, count, flag = 0; short i, run_count, num_flags_saved, max_flags; static long *buffer= NULL; ActionQueue *queue; if (buffer == NULL) { buffer = (long *)malloc((RECORD_CHUNK_SIZE * sizeof(long)) + RECORD_CHUNK_SIZE * sizeof(short)); } location= buffer; count= 0; // keeps track of how many bytes we'll save. last_flag= NONE; queue= get_player_recording_queue(player_index); // don't want to save too much stuff max_flags= MIN(RECORD_CHUNK_SIZE, get_recording_queue_size(player_index)); // save what's in the queue run_count= num_flags_saved= 0; for (i = 0; i<max_flags; i++) { flag = *(queue->buffer + queue->read_index); INCREMENT_QUEUE_COUNTER(queue->read_index); if (i && flag != last_flag) { *(short*)location = run_count; ((short*)location)++; *location++ = last_flag; count += sizeof(short) + sizeof(long); num_flags_saved += run_count; run_count = 1; } else { run_count++; } last_flag = flag; } // now save the final run *(short*)location = run_count; ((short*)location)++; *location++ = last_flag; count += sizeof(short) + sizeof(long); num_flags_saved += run_count; if (max_flags<RECORD_CHUNK_SIZE) { *(short*)location = END_OF_RECORDING_INDICATOR; ((short*)location)++; *location++ = 0; count += sizeof(short) + sizeof(long); num_flags_saved += RECORD_CHUNK_SIZE-max_flags; } write_file(replay.recording_file_refnum, count, buffer); replay.header.length+= count; vwarn(num_flags_saved == RECORD_CHUNK_SIZE, csprintf(temporary, "bad recording: %d flags, max=%d, count = %d;dm #%d #%d", num_flags_saved, max_flags, count, buffer, count)); }
/********************************************************************************************* * * Function: save_recording_queue_chunk * Purpose: saves one chunk of the queue to the recording file, using run-length encoding. * *********************************************************************************************/ void save_recording_queue_chunk( short player_index) { uint8 *location; uint32 last_flag, count, flag = 0; int16 i, run_count, num_flags_saved, max_flags; static uint8 *buffer= NULL; ActionQueue *queue; // The data format is (run length (int16)) + (action flag (uint32)) int DataSize = sizeof(int16) + sizeof(uint32); if (buffer == NULL) buffer = new byte[RECORD_CHUNK_SIZE * DataSize]; location= buffer; count= 0; // keeps track of how many bytes we'll save. last_flag= (uint32)NONE; queue= get_player_recording_queue(player_index); // don't want to save too much stuff max_flags= MIN(RECORD_CHUNK_SIZE, get_recording_queue_size(player_index)); // save what's in the queue run_count= num_flags_saved= 0; for (i = 0; i<max_flags; i++) { flag = queue->buffer[queue->read_index]; INCREMENT_QUEUE_COUNTER(queue->read_index); if (i && flag != last_flag) { ValueToStream(location,run_count); ValueToStream(location,last_flag); count += DataSize; num_flags_saved += run_count; run_count = 1; } else { run_count++; } last_flag = flag; } // now save the final run ValueToStream(location,run_count); ValueToStream(location,last_flag); count += DataSize; num_flags_saved += run_count; if (max_flags<RECORD_CHUNK_SIZE) { short end_indicator = END_OF_RECORDING_INDICATOR; ValueToStream(location,end_indicator); int32 end_flag = 0; ValueToStream(location,end_flag); count += DataSize; num_flags_saved += RECORD_CHUNK_SIZE-max_flags; } FilmFile.Write(count,buffer); replay.header.length+= count; vwarn(num_flags_saved == RECORD_CHUNK_SIZE, csprintf(temporary, "bad recording: %d flags, max=%d, count = %u;dm #%p #%u", num_flags_saved, max_flags, count, buffer, count)); }