Example #1
0
static int test_vbe(int x, int y, vbe_video_mode* mode)
{
	char buffer[256];
	struct vga_info info;
	struct vga_regs regs;
	adv_crtc crtc;

	draw_test_default();

	snprintf(buffer, sizeof(buffer), "vbe %s 0x%x %dx%dx%d [%dx%d]", index_name(video_index()), mode->mode, video_size_x(), video_size_y(), video_bits_per_pixel(), video_virtual_x(), video_virtual_y());
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;

	++y;

	vga_mode_get(&regs);
	vga_regs_info_get(&regs, &info);
	if (crtc_import(&crtc, &info, video_size_x(), video_size_y(), video_measured_vclock())==0) {
		++y;
		y = test_crtc(x, y, &crtc, 0, 1, 0);
	}

	++y;
	y = test_default_command(x, y);

	return y;
}
Example #2
0
/**
 * Update the sync state.
 * Enables or disables the video vertical sync from the game framerate
 * and the current speed state.
 */
void advance_video_update_sync(struct advance_video_context* context)
{
	double rate = video_measured_vclock();
	double reference = context->state.game_fps;

	context->state.sync_warming_up_flag = 1;

	if (rate > 10 && rate < 300) {
		context->state.mode_vclock = video_rate_scale_down(rate, reference);
		context->state.vsync_flag = context->config.vsync_flag;
	} else {
		/* out of range, surely NOT supported */
		context->state.mode_vclock = reference;
		context->state.vsync_flag = 0;
	}

	if (context->state.vsync_flag) {
		/* disable if no throttling */
		if (!context->state.sync_throttle_flag) {
			log_std(("emu:video: vsync disabled because throttle disactive\n"));
			context->state.vsync_flag = 0;
		}

		/* disable if turbo active */
		if (context->state.turbo_flag) {
			log_std(("emu:video: vsync disabled because turbo active\n"));
			context->state.vsync_flag = 0;
		}

		/* disable if fastest active */
		if (context->state.fastest_flag) {
			log_std(("emu:video: vsync disabled because fastest active\n"));
			context->state.vsync_flag = 0;
		}

		/* disable if measure active */
		if (context->state.measure_flag) {
			log_std(("emu:video: vsync disabled because measure active\n"));
			context->state.vsync_flag = 0;
		}

		/* disable the vsync flag if the frame rate is wrong */
		if (context->state.mode_vclock < reference * 0.97
			|| context->state.mode_vclock > reference * 1.03) {
			log_std(("emu:video: vsync disabled because the vclock is too different %g %g\n", reference, context->state.mode_vclock));
			context->state.vsync_flag = 0;
		}
	}
}
Example #3
0
int osd2_video_menu(int selected, unsigned input)
{
	struct advance_video_context* video_context = &CONTEXT.video;
	struct advance_global_context* global_context = &CONTEXT.global;
	struct advance_ui_context* ui_context = &CONTEXT.ui;

	struct ui_menu menu;
	unsigned mac;
	int resolution_index;
	int stretch_index;
	int vsync_index;
	int combine_index;
	int effect_index;
	int save_game_index;
	int save_resolution_index;
	int save_resolutionclock_index;
	int pipeline_index;
	int magnify_index;
	int index_index;
	int smp_index;
	int crash_index;
	int exit_index;
	char buffer[128];
	char freq[32];
	const char* text = 0;
	const char* option = 0;

	/* the menu data is not duplicated for the thread, so we have to wait for its completion */
	advance_video_thread_wait(video_context);

	if (selected >= 1)
		selected = selected - 1;
	else
		selected = 0;

	if (video_context->state.menu_sub_flag) {
		int ret = 0;
		switch (video_context->state.menu_sub_flag) {
		case 1: ret = video_mode_menu(video_context, ui_context, video_context->state.menu_sub_selected, input); break;
		case 2: ret = video_pipeline_menu(video_context, ui_context, video_context->state.menu_sub_selected, input); break;
		}
		switch (ret) {
		case -1: return -1;  /* hide interface */
		case 0: video_context->state.menu_sub_flag = 0; video_context->state.menu_sub_selected = 1; break;  /* close submenu */
		default: video_context->state.menu_sub_selected = ret; break;
		}
		return selected + 1;
	}

	advance_ui_menu_init(&menu);

	advance_ui_menu_title_insert(&menu, "Video Menu");

	snprintf(buffer, sizeof(buffer), "%dx%dx%d %.1f/%.1f/%.1f",
		video_size_x(),
		video_size_y(),
		video_bits_per_pixel(),
		(double)crtc_pclock_get(&video_context->state.crtc_effective) / 1E6,
		(double)crtc_hclock_get(&video_context->state.crtc_effective) / 1E3,
		(double)crtc_vclock_get(&video_context->state.crtc_effective)
	);
	advance_ui_menu_title_insert(&menu, buffer);

	resolution_index = advance_ui_menu_option_insert(&menu, "Mode...", video_context->config.resolution_buffer);

	if (!video_context->state.game_vector_flag) {
		if (strcmp(video_context->config.resolution_buffer, "auto") == 0) {
			switch (mode_current_magnify(video_context)) {
			default:
			case 1: text = "Magnify [1]"; break;
			case 2: text = "Magnify [2]"; break;
			case 3: text = "Magnify [3]"; break;
			case 4: text = "Magnify [4]"; break;
			}
			switch (video_context->config.magnify_factor) {
			default:
			case 0: option = "auto"; break;
			case 1: option = "1"; break;
			case 2: option = "2"; break;
			case 3: option = "3"; break;
			case 4: option = "4"; break;
			}
			magnify_index = advance_ui_menu_option_insert(&menu, text, option);
		} else {
			magnify_index = -1;
		}

		advance_ui_menu_title_insert(&menu, "Options");

		switch (mode_current_stretch(video_context)) {
		case STRETCH_NONE: text = "Resize [no]"; break;
		case STRETCH_INTEGER_XY: text = "Resize [integer]"; break;
		case STRETCH_INTEGER_X_FRACTIONAL_Y: text = "Resize [mixed]"; break;
		case STRETCH_FRACTIONAL_XY: text = "Resize [fractional]"; break;
		}
		switch (video_context->config.stretch) {
		case STRETCH_NONE: option = "no"; break;
		case STRETCH_INTEGER_XY: option = "integer"; break;
		case STRETCH_INTEGER_X_FRACTIONAL_Y: option = "mixed"; break;
		case STRETCH_FRACTIONAL_XY: option = "fractional"; break;
		}
		stretch_index = advance_ui_menu_option_insert(&menu, text, option);
	} else {
		magnify_index = -1;

		advance_ui_menu_title_insert(&menu, "Options");

		stretch_index = -1;
	}

	switch (video_index()) {
	case MODE_FLAGS_INDEX_PALETTE8:
		text = "Color [palette8]";
		break;
	case MODE_FLAGS_INDEX_BGR8:
		text = "Color [bgr8]";
		break;
	case MODE_FLAGS_INDEX_BGR15:
		text = "Color [bgr15]";
		break;
	case MODE_FLAGS_INDEX_BGR16:
		text = "Color [bgr16]";
		break;
	case MODE_FLAGS_INDEX_BGR32:
		text = "Color [bgr32]";
		break;
	case MODE_FLAGS_INDEX_YUY2:
		text = "Color [yuy2]";
		break;
	default:
		text = "Color [unknown]";
		break;
	}
	switch (video_context->config.index) {
	case MODE_FLAGS_INDEX_NONE:
		option = "auto";
		break;
	case MODE_FLAGS_INDEX_PALETTE8:
		option = "palette8";
		break;
	case MODE_FLAGS_INDEX_BGR8:
		option = "bgr8";
		break;
	case MODE_FLAGS_INDEX_BGR15:
		option = "bgr15";
		break;
	case MODE_FLAGS_INDEX_BGR16:
		option = "bgr16";
		break;
	case MODE_FLAGS_INDEX_BGR32:
		option = "bgr32";
		break;
	case MODE_FLAGS_INDEX_YUY2:
		option = "yuy2";
		break;
	default:
		option = "unknown";
		break;
	}
	index_index = advance_ui_menu_option_insert(&menu, text, option);

	switch (video_context->state.combine) {
	case COMBINE_NONE: text = "Resize Effect [no]"; break;
	case COMBINE_MAXMIN: text = "Resize Effect [max]"; break;
	case COMBINE_MEAN: text = "Resize Effect [mean]"; break;
	case COMBINE_FILTER: text = "Resize Effect [filter]"; break;
	case COMBINE_SCALEX: text = "Resize Effect [scalex]"; break;
	case COMBINE_SCALEK: text = "Resize Effect [scalek]"; break;
	case COMBINE_HQ: text = "Resize Effect [hq]"; break;
	case COMBINE_XBR: text = "Resize Effect [xbr]"; break;
	}
	switch (video_context->config.combine) {
	case COMBINE_AUTO: option = "auto"; break;
	case COMBINE_NONE: option = "no"; break;
	case COMBINE_MAXMIN: option = "max"; break;
	case COMBINE_MEAN: option = "mean"; break;
	case COMBINE_FILTER: option = "filter"; break;
	case COMBINE_SCALEX: option = "scalex"; break;
	case COMBINE_SCALEK: option = "scalek"; break;
	case COMBINE_HQ: option = "hq"; break;
	case COMBINE_XBR: option = "xbr"; break;
	}
	combine_index = advance_ui_menu_option_insert(&menu, text, option);

	switch (video_context->state.rgb_effect) {
	case EFFECT_NONE: text = "Rgb Effect [no]"; break;
	case EFFECT_RGB_TRIAD3PIX: text = "Rgb Effect [triad3dot]"; break;
	case EFFECT_RGB_TRIAD6PIX: text = "Rgb Effect [triad6dot]"; break;
	case EFFECT_RGB_TRIAD16PIX: text = "Rgb Effect [triad16dot]"; break;
	case EFFECT_RGB_TRIADSTRONG3PIX: text = "Rgb Effect [triadstrong3dot]"; break;
	case EFFECT_RGB_TRIADSTRONG6PIX: text = "Rgb Effect [triadstrong6dot]"; break;
	case EFFECT_RGB_TRIADSTRONG16PIX: text = "Rgb Effect [triadstrong16dot]"; break;
	case EFFECT_RGB_SCANDOUBLEHORZ: text = "Rgb Effect [scan2horz]"; break;
	case EFFECT_RGB_SCANTRIPLEHORZ: text = "Rgb Effect [scan3horz]"; break;
	case EFFECT_RGB_SCANDOUBLEVERT: text = "Rgb Effect [scan2vert]"; break;
	case EFFECT_RGB_SCANTRIPLEVERT: text = "Rgb Effect [scan3vert]"; break;
	}
	switch (video_context->config.rgb_effect) {
	case EFFECT_NONE: option = "no"; break;
	case EFFECT_RGB_TRIAD3PIX: option = "triad3dot"; break;
	case EFFECT_RGB_TRIAD6PIX: option = "triad6dot"; break;
	case EFFECT_RGB_TRIAD16PIX: option = "triad16dot"; break;
	case EFFECT_RGB_TRIADSTRONG3PIX: option = "triadstrong3dot"; break;
	case EFFECT_RGB_TRIADSTRONG6PIX: option = "triadstrong6dot"; break;
	case EFFECT_RGB_TRIADSTRONG16PIX: option = "triadstrong16dot"; break;
	case EFFECT_RGB_SCANDOUBLEHORZ: option = "scan2horz"; break;
	case EFFECT_RGB_SCANTRIPLEHORZ: option = "scan3horz"; break;
	case EFFECT_RGB_SCANDOUBLEVERT: option = "scan2vert"; break;
	case EFFECT_RGB_SCANTRIPLEVERT: option = "scan3vert"; break;
	}
	effect_index = advance_ui_menu_option_insert(&menu, text, option);

	switch (video_context->state.vsync_flag) {
	case 0: text = "Vsync [no]"; break;
	case 1:
		snprintf(freq, sizeof(freq), "Vsync [%.1f]", video_measured_vclock());
		text = freq;
		break;
	}
	switch (video_context->config.vsync_flag) {
	case 0: option = "no"; break;
	case 1: option = "yes"; break;
	}
	vsync_index = advance_ui_menu_option_insert(&menu, text, option);

#ifdef USE_SMP
	switch (video_context->config.smp_flag) {
	case 0: text = "SMP [no]"; break;
	case 1: text = "SMP [yes]"; break;
	}
	switch (video_context->config.smp_flag) {
	case 0: option = "no"; break;
	case 1: option = "yes"; break;
	}
	smp_index = advance_ui_menu_option_insert(&menu, text, option);
#else
	smp_index = -1;
#endif

	pipeline_index = advance_ui_menu_text_insert(&menu, "Details...");

	if (global_context->state.is_config_writable) {
		save_game_index = advance_ui_menu_text_insert(&menu, "Save for this game");

		if (!video_context->state.game_vector_flag) {
			save_resolutionclock_index = advance_ui_menu_text_insert(&menu, "Save for this game size/freq");
		} else {
			save_resolutionclock_index = -1;
		}

		if (video_context->state.game_vector_flag)
			text = "Save for all vector games";
		else
			text = "Save for this game size";
		save_resolution_index = advance_ui_menu_text_insert(&menu, text);
	} else {
		save_game_index = -1;
		save_resolution_index = -1;
		save_resolutionclock_index = -1;
	}

	if (video_context->config.crash_flag) {
		crash_index = advance_ui_menu_text_insert(&menu, "Crash");
	} else {
		crash_index = -1;
	}

	exit_index = advance_ui_menu_text_insert(&menu, "Return to Main Menu");

	mac = advance_ui_menu_done(&menu, ui_context, selected);

	if (input == OSD_INPUT_DOWN) {
		selected = (selected + 1) % mac;
	}

	if (input == OSD_INPUT_UP) {
		selected = (selected + mac - 1) % mac;
	}

	if (input == OSD_INPUT_SELECT) {
		if (selected == exit_index) {
			selected = -1;
		} else if (selected == resolution_index) {
			video_context->state.menu_sub_flag = 1;
		} else if (selected == pipeline_index) {
			video_context->state.menu_sub_flag = 2;
		} else if (selected == save_game_index) {
			advance_video_config_save(video_context, video_context->config.section_name_buffer);
		} else if (selected == save_resolution_index) {
			advance_video_config_save(video_context, video_context->config.section_resolution_buffer);
		} else if (selected == save_resolutionclock_index) {
			advance_video_config_save(video_context, video_context->config.section_resolutionclock_buffer);
		} else if (selected == crash_index) {
			target_crash();
		}
	}

	if (input == OSD_INPUT_RIGHT) {
		if (selected == combine_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.combine) {
			case COMBINE_AUTO: config.combine = COMBINE_NONE; break;
			case COMBINE_NONE: config.combine = COMBINE_MAXMIN; break;
			case COMBINE_MAXMIN: config.combine = COMBINE_MEAN; break;
			case COMBINE_MEAN: config.combine = COMBINE_FILTER; break;
			case COMBINE_FILTER: config.combine = COMBINE_SCALEX; break;
			case COMBINE_SCALEX: config.combine = COMBINE_SCALEK; break;
			case COMBINE_SCALEK: config.combine = COMBINE_HQ; break;
			case COMBINE_HQ: config.combine = COMBINE_XBR; break;
			case COMBINE_XBR: config.combine = COMBINE_AUTO; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == effect_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.rgb_effect) {
			case EFFECT_NONE: config.rgb_effect = EFFECT_RGB_TRIAD3PIX; break;
			case EFFECT_RGB_TRIAD3PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG3PIX; break;
			case EFFECT_RGB_TRIADSTRONG3PIX: config.rgb_effect = EFFECT_RGB_TRIAD6PIX; break;
			case EFFECT_RGB_TRIAD6PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG6PIX; break;
			case EFFECT_RGB_TRIADSTRONG6PIX: config.rgb_effect = EFFECT_RGB_TRIAD16PIX; break;
			case EFFECT_RGB_TRIAD16PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG16PIX; break;
			case EFFECT_RGB_TRIADSTRONG16PIX: config.rgb_effect = EFFECT_RGB_SCANDOUBLEHORZ; break;
			case EFFECT_RGB_SCANDOUBLEHORZ: config.rgb_effect = EFFECT_RGB_SCANTRIPLEHORZ; break;
			case EFFECT_RGB_SCANTRIPLEHORZ: config.rgb_effect = EFFECT_RGB_SCANDOUBLEVERT; break;
			case EFFECT_RGB_SCANDOUBLEVERT: config.rgb_effect = EFFECT_RGB_SCANTRIPLEVERT; break;
			case EFFECT_RGB_SCANTRIPLEVERT: config.rgb_effect = EFFECT_NONE; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == vsync_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.vsync_flag) {
			case 0: config.vsync_flag = 1; break;
			case 1: config.vsync_flag = 0; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == smp_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.smp_flag) {
			case 0: config.smp_flag = 1; break;
			case 1: config.smp_flag = 0; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == magnify_index) {
			struct advance_video_config_context config = video_context->config;
			if (config.magnify_factor == 4)
				config.magnify_factor = 0;
			else
				config.magnify_factor += 1;
			advance_video_reconfigure(video_context, &config);
		} else if (selected == index_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.index) {
			case MODE_FLAGS_INDEX_NONE: config.index = MODE_FLAGS_INDEX_PALETTE8; break;
			case MODE_FLAGS_INDEX_PALETTE8: config.index = MODE_FLAGS_INDEX_BGR8; break;
			case MODE_FLAGS_INDEX_BGR8: config.index = MODE_FLAGS_INDEX_BGR15; break;
			case MODE_FLAGS_INDEX_BGR15: config.index = MODE_FLAGS_INDEX_BGR16; break;
			case MODE_FLAGS_INDEX_BGR16: config.index = MODE_FLAGS_INDEX_BGR32; break;
			case MODE_FLAGS_INDEX_BGR32: config.index = MODE_FLAGS_INDEX_YUY2; break;
			case MODE_FLAGS_INDEX_YUY2: config.index = MODE_FLAGS_INDEX_NONE; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == stretch_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.stretch) {
			case STRETCH_NONE: config.stretch = STRETCH_FRACTIONAL_XY; break;
			case STRETCH_INTEGER_XY: config.stretch = STRETCH_NONE; break;
			case STRETCH_INTEGER_X_FRACTIONAL_Y: config.stretch = STRETCH_INTEGER_XY; break;
			case STRETCH_FRACTIONAL_XY: config.stretch = STRETCH_INTEGER_X_FRACTIONAL_Y; break;
			}
			advance_video_reconfigure(video_context, &config);
		}
	}

	if (input == OSD_INPUT_LEFT) {
		if (selected == combine_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.combine) {
			case COMBINE_AUTO: config.combine = COMBINE_XBR; break;
			case COMBINE_NONE: config.combine = COMBINE_AUTO; break;
			case COMBINE_MAXMIN: config.combine = COMBINE_NONE; break;
			case COMBINE_MEAN: config.combine = COMBINE_MAXMIN; break;
			case COMBINE_FILTER: config.combine = COMBINE_MEAN; break;
			case COMBINE_SCALEX: config.combine = COMBINE_FILTER; break;
			case COMBINE_SCALEK: config.combine = COMBINE_SCALEX; break;
			case COMBINE_HQ: config.combine = COMBINE_SCALEK; break;
			case COMBINE_XBR: config.combine = COMBINE_HQ; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == effect_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.rgb_effect) {
			case EFFECT_NONE: config.rgb_effect = EFFECT_RGB_SCANTRIPLEVERT; break;
			case EFFECT_RGB_TRIAD3PIX: config.rgb_effect = EFFECT_NONE; break;
			case EFFECT_RGB_TRIADSTRONG3PIX: config.rgb_effect = EFFECT_RGB_TRIAD3PIX; break;
			case EFFECT_RGB_TRIAD6PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG3PIX; break;
			case EFFECT_RGB_TRIADSTRONG6PIX: config.rgb_effect = EFFECT_RGB_TRIAD6PIX; break;
			case EFFECT_RGB_TRIAD16PIX: config.rgb_effect = EFFECT_RGB_TRIADSTRONG6PIX; break;
			case EFFECT_RGB_TRIADSTRONG16PIX: config.rgb_effect = EFFECT_RGB_TRIAD16PIX; break;
			case EFFECT_RGB_SCANDOUBLEHORZ: config.rgb_effect = EFFECT_RGB_TRIADSTRONG16PIX; break;
			case EFFECT_RGB_SCANTRIPLEHORZ: config.rgb_effect = EFFECT_RGB_SCANDOUBLEHORZ; break;
			case EFFECT_RGB_SCANDOUBLEVERT: config.rgb_effect = EFFECT_RGB_SCANTRIPLEHORZ; break;
			case EFFECT_RGB_SCANTRIPLEVERT: config.rgb_effect = EFFECT_RGB_SCANDOUBLEVERT; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == vsync_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.vsync_flag) {
			case 0: config.vsync_flag = 1; break;
			case 1: config.vsync_flag = 0; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == smp_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.smp_flag) {
			case 0: config.smp_flag = 1; break;
			case 1: config.smp_flag = 0;  break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == magnify_index) {
			struct advance_video_config_context config = video_context->config;
			if (config.magnify_factor == 0)
				config.magnify_factor = 4;
			else
				config.magnify_factor -= 1;
			advance_video_reconfigure(video_context, &config);
		} else if (selected == index_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.index) {
			case MODE_FLAGS_INDEX_NONE: config.index = MODE_FLAGS_INDEX_YUY2; break;
			case MODE_FLAGS_INDEX_PALETTE8: config.index = MODE_FLAGS_INDEX_NONE; break;
			case MODE_FLAGS_INDEX_BGR8: config.index = MODE_FLAGS_INDEX_PALETTE8; break;
			case MODE_FLAGS_INDEX_BGR15: config.index = MODE_FLAGS_INDEX_BGR8; break;
			case MODE_FLAGS_INDEX_BGR16: config.index = MODE_FLAGS_INDEX_BGR15; break;
			case MODE_FLAGS_INDEX_BGR32: config.index = MODE_FLAGS_INDEX_BGR16; break;
			case MODE_FLAGS_INDEX_YUY2: config.index = MODE_FLAGS_INDEX_BGR32; break;
			}
			advance_video_reconfigure(video_context, &config);
		} else if (selected == stretch_index) {
			struct advance_video_config_context config = video_context->config;
			switch (config.stretch) {
			case STRETCH_NONE: config.stretch = STRETCH_INTEGER_XY; break;
			case STRETCH_INTEGER_XY: config.stretch = STRETCH_INTEGER_X_FRACTIONAL_Y; break;
			case STRETCH_INTEGER_X_FRACTIONAL_Y: config.stretch = STRETCH_FRACTIONAL_XY; break;
			case STRETCH_FRACTIONAL_XY: config.stretch = STRETCH_NONE; break;
			}
			advance_video_reconfigure(video_context, &config);
		}
	}

	if (input == OSD_INPUT_CANCEL)
		selected = -1;

	if (input == OSD_INPUT_CONFIGURE)
		selected = -2;

	return selected + 1;
}
Example #4
0
static void video_frame_sync(struct advance_video_context* context)
{
	double current;
	double expected;

	current = advance_timer();

	if (context->state.sync_warming_up_flag) {
		/* syncronize the first time */
		if (context->state.vsync_flag) {
			video_wait_vsync();
			current = advance_timer();
		}

		context->state.sync_pivot = 0;
		context->state.sync_last = current;
		context->state.sync_skip_counter = 0;

		context->state.sync_warming_up_flag = 0;

		log_debug(("advance:sync: throttle warming up\n"));
	} else {
		double time_before_sync, time_after_delay, time_after_sync;

		time_before_sync = current;

		expected = context->state.sync_last + context->state.skip_step * (1 + context->state.sync_skip_counter);
		context->state.sync_skip_counter = 0;

		/* take only a part of the error, this increase the stability */
		context->state.sync_pivot *= 0.99;

		/* adjust with the previous error */
		expected += context->state.sync_pivot;

		/* the vsync is used only if all the frames are displayed */
		if ((video_flags() & MODE_FLAGS_RETRACE_WAIT_SYNC) != 0
			&& context->state.vsync_flag
			&& context->state.skip_level_full == SYNC_MAX
		) {
			/* wait until the retrace is near (3% early), otherwise if the */
			/* mode has a double freq the retrace may be the wrong one. */
			double early = 0.03 / video_measured_vclock();

			if (current < expected - early) {
				current = video_frame_wait(current, expected - early);
				time_after_delay = current;

				if (current < expected) {
					double after;
					video_wait_vsync();
					after = advance_timer();
					
					if (after - current > 1.05 / (double)video_measured_vclock()) {
						log_std(("ERROR:emu:video: sync wait too long. %g instead of %g (max %g)\n", after - current, early, 1.0 / (double)video_measured_vclock()));
					} else if (after - current > 1.05 * early) {
						log_std(("WARNING:emu:video: sync wait too long. %g instead of %g (max %g)\n", after - current, early, 1.0 / (double)video_measured_vclock()));
					}
					
					/* if a sync complete correctly reset the error to 0 */
					/* in this case the vsync is used for the correct clocking */
					expected = after;
					
					current = after;
				} else {
					log_std(("ERROR:emu:video: sync delay too big\n"));
				}
			} else {
				log_std(("ERROR:emu:video: too late for a video sync\n"));
				current = video_frame_wait(current, expected);
				time_after_delay = current;
			}
		} else {
			current = video_frame_wait(current, expected);
			time_after_delay = current;
		}

		time_after_sync = current;

		/* update the error state */
		context->state.sync_pivot = expected - current;

		if (fabs(context->state.sync_pivot) > context->state.skip_step / 50)
			log_std(("advance:sync: %.5f (err %6.1f%%) = %.5f + %.5f + %.5f < %.5f (compute + sleep + sync < max)\n", current - context->state.sync_last, context->state.sync_pivot * 100 / context->state.skip_step, time_before_sync - context->state.sync_last, time_after_delay - time_before_sync, time_after_sync - time_after_delay, context->state.skip_step));

		if (context->state.sync_pivot < - context->state.skip_step * 16) {
			/* if the error is too big (negative) the delay is unrecoverable */
			/* generally it happen with a virtual terminal switch */
			/* the best solution is to restart the sync computation */
			advance_video_update_skip(context);
			advance_video_update_sync(context);
		}

		context->state.sync_last = current;
	}
}
Example #5
0
static int test_crtc(int x, int y, adv_crtc* crtc, int print_clock, int print_measured_clock, int print_key)
{
	char buffer[256];

	snprintf(buffer, sizeof(buffer), "Horz  Vert");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;

	if (print_clock) {
		snprintf(buffer, sizeof(buffer), "%4.1f %5.1f %sClock Requested [kHz Hz]", crtc_hclock_get(crtc) / 1E3, crtc_vclock_get(crtc), print_key ? "     " : "");
		draw_string(x, y, buffer, DRAW_COLOR_WHITE);
		++y;
	}

	if (print_measured_clock) {
		snprintf(buffer, sizeof(buffer), "     %5.1f %sClock Measured [Hz]", video_measured_vclock(), print_key ? "     " : "");
		draw_string(x, y, buffer, DRAW_COLOR_WHITE);
		++y;
	}

	snprintf(buffer, sizeof(buffer), "%4d  %4d %sDisplay End", crtc->hde, crtc->vde, print_key ? "[qa] " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;

	snprintf(buffer, sizeof(buffer), "%4d  %4d %sRetrace Start", crtc->hrs, crtc->vrs, print_key ? "[ed] " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;
	if (!(crtc->hde<=crtc->hrs)) {
		snprintf(buffer, sizeof(buffer), "HDE<=HRS");
		draw_string(x, y, buffer, DRAW_COLOR_RED);
		++y;
	}
	if (!(crtc->vde<=crtc->vrs)) {
		snprintf(buffer, sizeof(buffer), "VDE<=VRS");
		draw_string(x, y, buffer, DRAW_COLOR_RED);
		++y;
	}

	snprintf(buffer, sizeof(buffer), "%4d  %4d %sRetrace End", crtc->hre, crtc->vre, print_key ? "[rf] " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;
	if (!(crtc->hrs<crtc->hre)) {
		snprintf(buffer, sizeof(buffer), "HRS<HRE");
		draw_string(x, y, buffer, DRAW_COLOR_RED);
		++y;
	}
	if (!(crtc->vrs<crtc->vre)) {
		snprintf(buffer, sizeof(buffer), "VRE<VRE");
		draw_string(x, y, buffer, DRAW_COLOR_RED);
		++y;
	}

	snprintf(buffer, sizeof(buffer), "%4d  %4d %sTotal", crtc->ht, crtc->vt, print_key ? "[yh] " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;
	if (!(crtc->hre<=crtc->ht)) {
		snprintf(buffer, sizeof(buffer), "HRE<=HT");
		draw_string(x, y, buffer, DRAW_COLOR_RED);
		++y;
	}
	if (!(crtc->vre<=crtc->vt)) {
		snprintf(buffer, sizeof(buffer), "VRE<=VT");
		draw_string(x, y, buffer, DRAW_COLOR_RED);
		++y;
	}

	snprintf(buffer, sizeof(buffer), "   %c     %c %sPolarization", crtc_is_nhsync(crtc) ? '-' : '+', crtc_is_nvsync(crtc) ? '-' : '+', print_key ? "[uj] " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;

	snprintf(buffer, sizeof(buffer), "      %4s %sDoublescan", crtc_is_doublescan(crtc) ? "on" : "off", print_key ? "[x]  " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;

	snprintf(buffer, sizeof(buffer), "      %4s %sInterlaced", crtc_is_interlace(crtc) ? "on" : "off", print_key ? "[c]  " : "");
	draw_string(x, y, buffer, DRAW_COLOR_WHITE);
	++y;

	if (print_clock) {
		snprintf(buffer, sizeof(buffer), "%4.2f      %sPixelclock [MHz]", (double)crtc->pixelclock / 1E6, print_key ? "[v]  " : "");
		draw_string(x, y, buffer, DRAW_COLOR_WHITE);
		++y;
	}

	if (print_key) {
		++y;
		draw_string(x, y, "Q...U  Inc horz (SHIFT dec)", DRAW_COLOR_WHITE);
		++y;
		draw_string(x, y, "A...J  Inc vert (SHIFT dec)", DRAW_COLOR_WHITE);
		++y;
		draw_string(x, y, "I,K    Inc horz/vert size (SHIFT dec)", DRAW_COLOR_WHITE);
		++y;
		draw_string(x, y, "XCV    Flip flag", DRAW_COLOR_WHITE);
		++y;
		draw_string(x, y, "ARROWS Center", DRAW_COLOR_WHITE);
		++y;
	}

	return y;
}