Пример #1
0
static void record_action_flags(
	short player_identifier, 
	long *action_flags, 
	short count)
{
	short index;
	ActionQueue  *queue;
	
	queue= get_player_recording_queue(player_identifier);
	assert(queue && queue->write_index >= 0 && queue->write_index < MAXIMUM_QUEUE_SIZE);
	for (index= 0; index<count; index++)
	{
		*(queue->buffer + queue->write_index) = *action_flags++;
		INCREMENT_QUEUE_COUNTER(queue->write_index);
		if (queue->write_index == queue->read_index)
		{
			dprintf("blew recording queue for player %d", player_identifier);
		}
	}
}
Пример #2
0
/*********************************************************************************************
 *
 * 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;
}
Пример #3
0
static void read_recording_queue_chunks(
	void)
{
	long i, sizeof_read, action_flags;
	short count, player_index, num_flags;
	ActionQueue *queue;
	short error;
	
	for (player_index = 0; player_index < dynamic_world->player_count; player_index++)
	{
		queue= get_player_recording_queue(player_index);
		for (count = 0; count < RECORD_CHUNK_SIZE; )
		{
			if (replay.resource_data)
			{
				boolean hit_end= FALSE;
				
				if (replay.film_resource_offset >= replay.resource_data_size)
				{
					hit_end = TRUE;
				}
				else
				{
					num_flags = * (short *) (replay.resource_data + replay.film_resource_offset);
					replay.film_resource_offset += sizeof(num_flags);
					action_flags = *(long *) (replay.resource_data + replay.film_resource_offset);
					replay.film_resource_offset+= sizeof(action_flags);
				}
				
				if (hit_end || num_flags == END_OF_RECORDING_INDICATOR)
				{
					replay.have_read_last_chunk= TRUE;
					break;
				}
			}
			else
			{
				sizeof_read = sizeof(num_flags);
				error= vblFSRead(replay.recording_file_refnum, &sizeof_read, &num_flags);
				if (!error)
				{
					sizeof_read = sizeof(action_flags);
					error= vblFSRead(replay.recording_file_refnum, &sizeof_read, &action_flags);
					assert(!error || (error == errHitFileEOF && sizeof_read == sizeof(action_flags)));
				}
				
				if ((error == errHitFileEOF && sizeof_read != sizeof(long)) || num_flags == END_OF_RECORDING_INDICATOR)
				{
					replay.have_read_last_chunk = TRUE;
					break;
				}
			}
			assert(replay.have_read_last_chunk || num_flags);
			count += num_flags;
			vassert((num_flags != 0 && count <= RECORD_CHUNK_SIZE) || replay.have_read_last_chunk, 
				csprintf(temporary, "num_flags = %d, count = %d", num_flags, count));
			for (i = 0; i < num_flags; i++)
			{
				*(queue->buffer + queue->write_index) = action_flags;
				INCREMENT_QUEUE_COUNTER(queue->write_index);
				assert(queue->read_index != queue->write_index);
			}
		}
		assert(replay.have_read_last_chunk || count == RECORD_CHUNK_SIZE);
	}

	return;
}
Пример #4
0
/*********************************************************************************************
 *
 * 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));
}
Пример #5
0
static void read_recording_queue_chunks(
	void)
{
	logContext("reading recording queue chunks");

	int32 i, sizeof_read;
	uint32 action_flags; 
	int16 count, player_index, num_flags;
	ActionQueue *queue;
	
	for (player_index = 0; player_index < dynamic_world->player_count; player_index++)
	{
		queue= get_player_recording_queue(player_index);
		for (count = 0; count < RECORD_CHUNK_SIZE; )
		{
			if (replay.resource_data)
			{
				bool hit_end= false;
				
				if (replay.film_resource_offset >= replay.resource_data_size)
				{
					hit_end = true;
				}
				else
				{
					uint8* S;
					S = (uint8 *)(replay.resource_data + replay.film_resource_offset);
					StreamToValue(S,num_flags);
					replay.film_resource_offset += sizeof(num_flags);
					S = (uint8 *)(replay.resource_data + replay.film_resource_offset);
					StreamToValue(S,action_flags);
					replay.film_resource_offset+= sizeof(action_flags);
				}
				
				if (hit_end || num_flags == END_OF_RECORDING_INDICATOR)
				{
					replay.have_read_last_chunk= true;
					break;
				}
			}
			else
			{
				sizeof_read = sizeof(num_flags);
				uint8 NumFlagsBuffer[sizeof(num_flags)];
				bool HitEOF = false;
				if (vblFSRead(FilmFile, &sizeof_read, NumFlagsBuffer, HitEOF))
				{
					uint8 *S = NumFlagsBuffer;
					StreamToValue(S,num_flags);
					sizeof_read = sizeof(action_flags);
					uint8 ActionFlagsBuffer[sizeof(action_flags)];
					bool status = vblFSRead(FilmFile, &sizeof_read, ActionFlagsBuffer, HitEOF);
					S = ActionFlagsBuffer;
					StreamToValue(S,action_flags);
					assert(status || (HitEOF && sizeof_read == sizeof(action_flags)));
				}
				
				if ((HitEOF && sizeof_read != sizeof(action_flags)) || num_flags == END_OF_RECORDING_INDICATOR)
				{
					replay.have_read_last_chunk = true;
					break;
				}
			}

			if (!(replay.have_read_last_chunk || num_flags))
			{
				logAnomaly("chunk contains no flags");
			}

			count += num_flags;

			for (i = 0; i < num_flags; i++)
			{
				*(queue->buffer + queue->write_index) = action_flags;
				INCREMENT_QUEUE_COUNTER(queue->write_index);
				assert(queue->read_index != queue->write_index);
			}
		}
		assert(replay.have_read_last_chunk || count == RECORD_CHUNK_SIZE);
	}
}
Пример #6
0
/*********************************************************************************************
 *
 * 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));
}