static void network_test_delay(void) { int i, j; BYTE new_frame_delta; BYTE buf[0x60]; long packet_delay[NUM_OF_TESTPACKETS]; char st[256]; vsyncarch_init(); ui_display_statustext(translate_text(IDGS_TESTING_BEST_FRAME_DELAY), 0); if (network_mode == NETWORK_SERVER_CONNECTED) { for (i = 0; i < NUM_OF_TESTPACKETS; i++) { *((unsigned long*)buf) = vsyncarch_gettime(); if (network_send_buffer(network_socket, buf, sizeof(buf)) < 0 || network_recv_buffer(network_socket, buf, sizeof(buf)) < 0) return; packet_delay[i] = vsyncarch_gettime() - *((unsigned long*)buf); } /* Sort the packets delays*/ for (i = 0; i < NUM_OF_TESTPACKETS - 1; i++) { for (j = i + 1; j < NUM_OF_TESTPACKETS; j++) { if (packet_delay[i] < packet_delay[j]) { long d = packet_delay[i]; packet_delay[i] = packet_delay[j]; packet_delay[j] = d; } } #ifdef NETWORK_DEBUG log_debug("packet_delay[%d]=%ld",i,packet_delay[i]); #endif } #ifdef NETWORK_DEBUG log_debug("vsyncarch_frequency = %ld", vsyncarch_frequency()); #endif /* calculate delay with 90% of packets beeing fast enough */ /* FIXME: This needs some further investigation */ new_frame_delta = 5 + (BYTE)(vsync_get_refresh_frequency() * packet_delay[(int)(0.1 * NUM_OF_TESTPACKETS)] / (float)vsyncarch_frequency()); network_send_buffer(network_socket, &new_frame_delta, sizeof(new_frame_delta)); } else { /* network_mode == NETWORK_CLIENT */ for (i = 0; i < NUM_OF_TESTPACKETS; i++) { if (network_recv_buffer(network_socket, buf, sizeof(buf)) < 0 || network_send_buffer(network_socket, buf, sizeof(buf)) < 0) return; } network_recv_buffer(network_socket, &new_frame_delta, sizeof(new_frame_delta)); } network_free_frame_event_list(); frame_delta = new_frame_delta; network_init_frame_event_list(); sprintf(st, translate_text(IDGS_USING_D_FRAMES_DELAY), frame_delta); log_debug("netplay connected with %d frames delta.", frame_delta); ui_display_statustext(st, 1); }
static void network_client_connect_trap(WORD addr, void *data) { BYTE *buf; size_t buf_size; BYTE recv_buf4[4]; event_list_state_t *settings_list; /* Set proper settings */ if (resources_set_event_safe() < 0) ui_error("Warning! Failed to set netplay-safe settings."); /* Receive settings that need to be same as on server */ if (network_recv_buffer(network_socket, recv_buf4, 4) < 0) return; buf_size = (size_t)util_le_buf4_to_int(recv_buf4); buf = lib_malloc(buf_size); if (network_recv_buffer(network_socket, buf, buf_size) < 0) return; settings_list = network_create_event_list(buf); lib_free(buf); event_playback_event_list(settings_list); event_clear_list(settings_list); lib_free(settings_list); /* read the snapshot */ if (machine_read_snapshot(snapshotfilename, 0) != 0) { #ifdef HAS_TRANSLATION ui_error(translate_text(IDGS_CANNOT_OPEN_SNAPSHOT_FILE_S), snapshotfilename); #else ui_error(_("Cannot open snapshot file %s"), snapshotfilename); #endif lib_free(snapshotfilename); return; } current_send_frame = 0; last_received_frame = 0; network_mode = NETWORK_CLIENT; network_test_delay(); lib_free(snapshotfilename); }
static void network_hook_connected_receive(void) { BYTE *remote_event_buf = NULL; unsigned int recv_len; BYTE recv_len4[4]; event_list_state_t *remote_event_list; event_list_state_t *client_event_list, *server_event_list; suspended = 0; if (current_frame == frame_delta - 1) frame_buffer_full = 1; if (frame_buffer_full) { do { if (network_recv_buffer(network_socket, recv_len4, 4) < 0) { ui_display_statustext(translate_text(IDGS_REMOTE_HOST_DISCONNECTED), 1); network_disconnect(); return; } recv_len = util_le_buf4_to_int(recv_len4); if (recv_len == 0 && suspended == 0) { /* remote host suspended emulation */ ui_display_statustext(translate_text(IDGS_REMOTE_HOST_SUSPENDING), 0); suspended = 1; vsync_suspend_speed_eval(); } } while (recv_len == 0); if (suspended == 1) ui_display_statustext("", 0); remote_event_buf = lib_malloc(recv_len); if (network_recv_buffer(network_socket, remote_event_buf, recv_len) < 0) { lib_free(remote_event_buf); return; } #ifdef NETWORK_DEBUG t3 = vsyncarch_gettime(); #endif remote_event_list = network_create_event_list(remote_event_buf); lib_free(remote_event_buf); if (network_mode == NETWORK_SERVER_CONNECTED) { client_event_list = remote_event_list; server_event_list = &(frame_event_list[frame_to_play]); } else { server_event_list = remote_event_list; client_event_list = &(frame_event_list[frame_to_play]); } /* test for sync */ if (client_event_list->base->type == EVENT_SYNC_TEST && server_event_list->base->type == EVENT_SYNC_TEST) { int i; for (i = 0; i < 5; i++) { if (((DWORD *)client_event_list->base->data)[i] != ((DWORD *)server_event_list->base->data)[i]) { ui_error(translate_text(IDGS_NETWORK_OUT_OF_SYNC)); network_disconnect(); /* shouldn't happen but resyncing would be nicer */ break; } } } /* replay the event_lists; server first, then client */ event_playback_event_list(server_event_list); event_playback_event_list(client_event_list); event_clear_list(remote_event_list); lib_free(remote_event_list); } network_prepare_next_frame(); #ifdef NETWORK_DEBUG t4 = vsyncarch_gettime(); #endif }
int network_connect_client(void) { vice_network_socket_address_t * server_addr; FILE *f; BYTE *buf; BYTE recv_buf4[4]; size_t buf_size; if (network_mode != NETWORK_IDLE) return -1; vsync_suspend_speed_eval(); snapshotfilename = NULL; f = archdep_mkstemp_fd(&snapshotfilename, MODE_WRITE); if (f == NULL) { ui_error(translate_text(IDGS_CANNOT_CREATE_SNAPSHOT_S_SELECT)); return -1; } server_addr = vice_network_address_generate(server_name, server_port); if (server_addr == NULL) { ui_error(translate_text(IDGS_CANNOT_RESOLVE_S), server_name); return -1; } network_socket = vice_network_client(server_addr); vice_network_address_close(server_addr); server_addr = NULL; if ( ! network_socket ) { ui_error(translate_text(IDGS_CANNOT_CONNECT_TO_S), server_name, server_port); lib_free(snapshotfilename); return -1; } ui_display_statustext(translate_text(IDGS_RECEIVING_SNAPSHOT_SERVER), 0); if (network_recv_buffer(network_socket, recv_buf4, 4) < 0) { lib_free(snapshotfilename); vice_network_socket_close(network_socket); return -1; } buf_size = (size_t)util_le_buf4_to_int(recv_buf4); buf = lib_malloc(buf_size); if (network_recv_buffer(network_socket, buf, (int)buf_size) < 0) { lib_free(snapshotfilename); vice_network_socket_close(network_socket); return -1; } if (fwrite(buf, 1, buf_size, f) <= 0) { log_debug("network_connect_client write failed."); } fclose(f); lib_free(buf); interrupt_maincpu_trigger_trap(network_client_connect_trap, (void *)0); vsync_suspend_speed_eval(); return 0; }