changeset 1957:ba06346611a1

Fix some netplay issues
author Mike Pavone <pavone@retrodev.com>
date Sat, 02 May 2020 00:52:21 -0700
parents 275f1c4bdb25
children 9c01945b5d20
files event_log.c event_log.h gen_player.c vdp.c
diffstat 4 files changed, 59 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/event_log.c	Fri May 01 23:39:45 2020 -0700
+++ b/event_log.c	Sat May 02 00:52:21 2020 -0700
@@ -124,7 +124,7 @@
 			}
 			return;
 		}
-	} else if (type == last_event_type && delta == last_delta) {
+	} else if (type == last_event_type && delta == last_delta && type != EVENT_FLUSH) {
 		//make some room
 		save_int8(&buffer, 0);
 		//shift existing command
@@ -246,6 +246,11 @@
 	last = cycle;
 	save_buffer8(&buffer, payload, size);
 	if (listen_sock && buffer.size > 1280) {
+		if (multi_count) {
+			buffer.data[multi_start] |= multi_count - 2;
+			multi_count = 0;
+			last_event_type = 0xFF;
+		}
 		flush_socket();
 	}
 }
@@ -394,6 +399,40 @@
 	setsockopt(reader->socket, IPPROTO_TCP, TCP_NODELAY, (const char *)&flag, sizeof(flag));
 }
 
+static void read_from_socket(event_reader *reader)
+{
+	if (reader->storage - (reader->buffer.size - reader->buffer.cur_pos) < 128 * 1024) {
+		reader->storage *= 2;
+		uint8_t *new_buf = malloc(reader->storage);
+		memcpy(new_buf, reader->buffer.data + reader->buffer.cur_pos, reader->buffer.size - reader->buffer.cur_pos);
+		free(reader->buffer.data);
+		reader->buffer.data = new_buf;
+		reader->buffer.size -= reader->buffer.cur_pos;
+		reader->buffer.cur_pos = 0;
+	} else if (reader->buffer.cur_pos >= reader->buffer.size/2 && reader->buffer.size >= reader->storage/2) {
+		memmove(reader->buffer.data, reader->buffer.data + reader->buffer.cur_pos, reader->buffer.size - reader->buffer.cur_pos);
+		reader->buffer.size -= reader->buffer.cur_pos;
+		reader->buffer.cur_pos = 0;
+	}
+	int bytes = recv(reader->socket, reader->buffer.data + reader->buffer.size, reader->storage - reader->buffer.size, 0);
+	if (bytes >= 0) {
+		reader->buffer.size += bytes;
+	} else if (!socket_error_is_wouldblock()) {
+		fatal_error("Connection closed, error = %X\n", socket_last_error());
+	}
+}
+
+void reader_ensure_data(event_reader *reader, size_t bytes)
+{
+	if (reader->socket && reader->buffer.size - reader->buffer.cur_pos < bytes) {
+		socket_blocking(reader->socket, 1);
+		while (reader->buffer.size - reader->buffer.cur_pos < bytes) {
+			read_from_socket(reader);
+		}
+		socket_blocking(reader->socket, 0);
+	}
+}
+
 uint8_t reader_next_event(event_reader *reader, uint32_t *cycle_out)
 {
 	if (reader->repeat_remaining) {
@@ -403,34 +442,8 @@
 		return reader->repeat_event;
 	}
 	if (reader->socket) {
-		uint8_t blocking = 0;
-		if (reader->buffer.size - reader->buffer.cur_pos < 9) {
-			//set back to block mode
-			socket_blocking(reader->socket, 1);
-			blocking = 1;
-		}
-		if (reader->storage - (reader->buffer.size - reader->buffer.cur_pos) < 128 * 1024) {
-			reader->storage *= 2;
-			uint8_t *new_buf = malloc(reader->storage);
-			memcpy(new_buf, reader->buffer.data + reader->buffer.cur_pos, reader->buffer.size - reader->buffer.cur_pos);
-			free(reader->buffer.data);
-			reader->buffer.data = new_buf;
-			reader->buffer.size -= reader->buffer.cur_pos;
-			reader->buffer.cur_pos = 0;
-		} else if (reader->buffer.cur_pos >= reader->buffer.size/2 && reader->buffer.size >= reader->storage/2) {
-			memmove(reader->buffer.data, reader->buffer.data + reader->buffer.cur_pos, reader->buffer.size - reader->buffer.cur_pos);
-			reader->buffer.size -= reader->buffer.cur_pos;
-			reader->buffer.cur_pos = 0;
-		}
-		int bytes = recv(reader->socket, reader->buffer.data + reader->buffer.size, reader->storage - reader->buffer.size, 0);
-		if (bytes >= 0) {
-			reader->buffer.size += bytes;
-			if (blocking && reader->buffer.size - reader->buffer.cur_pos >= 9) {
-				socket_blocking(reader->socket, 0);
-			}
-		} else if (!socket_error_is_wouldblock()) {
-			printf("Connection closed, error = %X\n", socket_last_error());
-		}
+		read_from_socket(reader);
+		reader_ensure_data(reader, 1);
 	}
 	uint8_t header = load_int8(&reader->buffer);
 	uint8_t ret;
@@ -439,15 +452,18 @@
 	if ((header & 0xF0) == (EVENT_MULTI << 4)) {
 		reader->repeat_remaining = (header & 0xF) + 1;
 		multi_start = 1;
+		reader_ensure_data(reader, 1);
 		header = load_int8(&reader->buffer);
 	}
 	if ((header & 0xF0) < FORMAT_3BYTE) {
 		delta = (header & 0xF) + 16;
 		ret = header >> 4;
 	} else if ((header & 0xF0) == FORMAT_3BYTE) {
+		reader_ensure_data(reader, 2);
 		delta = load_int16(&reader->buffer);
 		ret = header & 0xF;
 	} else {
+		reader_ensure_data(reader, 3);
 		delta = load_int8(&reader->buffer) << 16;
 		//sign extend 24-bit delta to 32-bit
 		if (delta & 0x800000) {
@@ -463,11 +479,13 @@
 	*cycle_out = reader->last_cycle + delta;
 	reader->last_cycle = *cycle_out;
 	if (ret == EVENT_ADJUST) {
+		reader_ensure_data(reader, 4);
 		size_t old_pos = reader->buffer.cur_pos;
 		uint32_t adjust = load_int32(&reader->buffer);
 		reader->buffer.cur_pos = old_pos;
 		reader->last_cycle -= adjust;
 	} else if (ret == EVENT_STATE) {
+		reader_ensure_data(reader, 8);
 		reader->last_cycle = load_int32(&reader->buffer);
 		reader->last_word_address = load_int8(&reader->buffer) << 16;
 		reader->last_word_address |= load_int16(&reader->buffer);
--- a/event_log.h	Fri May 01 23:39:45 2020 -0700
+++ b/event_log.h	Sat May 02 00:52:21 2020 -0700
@@ -48,6 +48,7 @@
 void init_event_reader(event_reader *reader, uint8_t *data, size_t size);
 void init_event_reader_tcp(event_reader *reader, char *address, char *port);
 uint8_t reader_next_event(event_reader *reader, uint32_t *cycle_out);
+void reader_ensure_data(event_reader *reader, size_t bytes);
 uint8_t reader_system_type(event_reader *reader);
 void reader_send_gamepad_event(event_reader *reader, uint8_t pad, uint8_t button, uint8_t down);
 
--- a/gen_player.c	Fri May 01 23:39:45 2020 -0700
+++ b/gen_player.c	Sat May 02 00:52:21 2020 -0700
@@ -47,10 +47,12 @@
 			break;
 		case EVENT_PSG_REG:
 			sync_sound(player, cycle);
+			reader_ensure_data(&player->reader, 1);
 			psg_write(player->psg, load_int8(&player->reader.buffer));
 			break;
 		case EVENT_YM_REG: {
 			sync_sound(player, cycle);
+			reader_ensure_data(&player->reader, 3);
 			uint8_t part = load_int8(&player->reader.buffer);
 			uint8_t reg = load_int8(&player->reader.buffer);
 			uint8_t value = load_int8(&player->reader.buffer);
@@ -62,12 +64,10 @@
 			ym_data_write(player->ym, value);
 			break;
 		case EVENT_STATE: {
+			reader_ensure_data(&player->reader, 3);
 			uint32_t size = load_int8(&player->reader.buffer) << 16;
 			size |= load_int16(&player->reader.buffer);
-			if (player->reader.buffer.size - player->reader.buffer.cur_pos < size) {
-				puts("State has not been fully loaded!");
-				exit(1);
-			}
+			reader_ensure_data(&player->reader, size);
 			deserialize_buffer buffer;
 			init_deserialize(&buffer, player->reader.buffer.data + player->reader.buffer.cur_pos, size);
 			register_section_handler(&buffer, (section_handler){.fun = vdp_deserialize, .data = player->vdp}, SECTION_VDP);
--- a/vdp.c	Fri May 01 23:39:45 2020 -0700
+++ b/vdp.c	Sat May 02 00:52:21 2020 -0700
@@ -4571,26 +4571,33 @@
 	switch (event)
 	{
 	case EVENT_VRAM_BYTE:
+		reader_ensure_data(reader, 3);
 		address = load_int16(buffer);
 		break;
 	case EVENT_VRAM_BYTE_DELTA:
+		reader_ensure_data(reader, 2);
 		address = reader->last_byte_address + load_int8(buffer);
 		break;
 	case EVENT_VRAM_BYTE_ONE:
+		reader_ensure_data(reader, 1);
 		address = reader->last_byte_address + 1;
 		break;
 	case EVENT_VRAM_BYTE_AUTO:
+		reader_ensure_data(reader, 1);
 		address = reader->last_byte_address + context->regs[REG_AUTOINC];
 		break;
 	case EVENT_VRAM_WORD:
+		reader_ensure_data(reader, 4);
 		address = load_int8(buffer) << 16;
 		address |= load_int16(buffer);
 		break;
 	case EVENT_VRAM_WORD_DELTA:
+		reader_ensure_data(reader, 3);
 		address = reader->last_word_address + load_int8(buffer);
 		break;
 	case EVENT_VDP_REG:
 	case EVENT_VDP_INTRAM:
+		reader_ensure_data(reader, event == EVENT_VDP_REG ? 2 : 3);
 		address = load_int8(buffer);
 		break;
 	}