|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Supporting functions for timekeeping in event.h
5: *
6: * Copyright 1995-2007 Bernd Schmidt
7: */
8:
9: #include "sysconfig.h"
10: #include "sysdeps.h"
11:
12: #include <ctype.h>
13: #include <assert.h>
14:
15: #include "options.h"
16: #include "threaddep/thread.h"
17: #include "uae.h"
18: #include "gensound.h"
19: #include "sounddep/sound.h"
20: #include "events.h"
21: #include "memory.h"
22: #include "custom.h"
23:
24: /* Events */
25:
26: unsigned long int currcycle, nextevent;
27: struct ev eventtab[ev_max];
28:
29: /* Time taken for one frame given the current display settings
30: (NTSC vs. PAL). */
31: frame_time_t vsynctime;
32: /* Timestamps of the next VSYNC event. */
33: frame_time_t vsyncmintime;
34:
35: int vsyncmintime_valid;
36:
37: /* Set if gettimeofday has high enough resolution for our purposes. */
38: int use_gtod = 0;
39:
40: /* Adjusted in do_cycles to keep track of how many gettimeofday calls
41: we can safely afford to skip. */
42: unsigned long nr_gtod_to_skip = 50000;
43: /* An upper bound on the previous value, determined at runtime. */
44: unsigned long max_gtod_to_skip = ULONG_MAX;
45:
46: /* First time we measured in do_cycles when waiting for vsyncmintime. */
47: frame_time_t first_measured_gtod;
48: /* Number of gettimeofday calls while waiting for vsyncmintime.
49: Affected by nr_gtod_to_skip. */
50: unsigned long nr_gtod_done;
51: /* A counter used internally by do_cycles to skip calls to gettimeofday. */
52: unsigned long gtod_counter;
53:
1.1.1.2 ! root 54: /* Set by the sound initialization code if the sound code can be used for
! 55: letting the m68k get extra cycles. */
! 56: int sync_with_sound;
! 57:
! 58: /* The number of ticks in a frame_time_t per second. */
! 59: unsigned long syncbase;
1.1 root 60:
61: int is_lastline;
1.1.1.2 ! root 62: volatile int delaying_for_sound;
! 63:
! 64: unsigned long gtod_resolution, gtod_secs;
! 65:
! 66: void init_gtod (void)
! 67: {
! 68: struct timeval tv1, tv2;
! 69: gettimeofday (&tv1, NULL);
! 70: do {
! 71: gettimeofday (&tv2, NULL);
! 72: } while (tv1.tv_sec == tv2.tv_sec
! 73: && tv1.tv_usec == tv2.tv_usec);
! 74:
! 75: gtod_resolution = (tv2.tv_usec - tv1.tv_usec + 1000000 * (tv2.tv_sec - tv1.tv_sec));
! 76: if (gtod_resolution < 1000) {
! 77: use_gtod = 1;
! 78: syncbase = 1000000;
! 79: }
! 80: }
1.1 root 81:
82: void reset_frame_rate_hack (void)
83: {
84: if (currprefs.m68k_speed != -1)
85: return;
86:
1.1.1.2 ! root 87: if (! sync_with_sound && ! use_gtod) {
1.1 root 88: currprefs.m68k_speed = 0;
89: return;
90: }
91:
92: vsyncmintime_valid = 0;
93: is_lastline = 0;
94: vsyncmintime = get_current_time(1);
95: vsyncmintime += vsynctime;
96: write_log ("Resetting frame rate hack\n");
97: }
98:
99: void compute_vsynctime (void)
100: {
101: vsynctime = syncbase / vblank_hz;
102: if (use_gtod)
103: vsynctime -= gtod_resolution < 100 ? 100 : gtod_resolution;
1.1.1.2 ! root 104: if (currprefs.produce_sound > 1 && !sync_with_sound) {
1.1 root 105: vsynctime = vsynctime * 19 / 20;
106: }
107: }
108:
109: void time_vsync (void)
110: {
1.1.1.2 ! root 111: if (sync_with_sound) {
! 112: /* We don't strictly need it, but keep vsyncmintime accurate. */
! 113: if (use_gtod) {
! 114: vsyncmintime = get_current_time(1) + vsynctime;
! 115: nr_gtod_done = 0;
! 116: vsyncmintime_valid = 1;
! 117: }
! 118: return;
! 119: }
! 120:
1.1 root 121: if (vsyncmintime_valid) {
1.1.1.2 ! root 122: if (nr_gtod_done > 50 && nr_gtod_to_skip < ULONG_MAX / 2) {
! 123: /* Try to reduce the number of gtod calls per frame - 50
! 124: should be enough, so whenever we exceed that number,
! 125: increase the number of gtod calls we skip - about 12%
! 126: each time. */
! 127: nr_gtod_to_skip += nr_gtod_to_skip / 8;
1.1 root 128: }
129: }
130:
131: if (currprefs.m68k_speed == -1) {
132: frame_time_t curr_time = get_current_time (1);
133: /* If we got behind in one frame, try catching up by using the
134: previous vsyncmintime as a base. If we get too far behind,
135: give up and reset. */
136: if (vsyncmintime_valid
137: && curr_time > vsyncmintime
138: && curr_time < vsyncmintime + vsynctime / 2)
139: vsyncmintime += vsynctime;
140: else
141: vsyncmintime = curr_time + vsynctime;
142: nr_gtod_done = 0;
143: vsyncmintime_valid = 1;
144: } else {
1.1.1.2 ! root 145: /* No sound, and not using maximum CPU speed: delay until the frame
! 146: has taken 20ms. */
! 147: if (currprefs.produce_sound < 2 && vsyncmintime_valid && use_gtod) {
1.1 root 148: frame_time_t curr_time;
149: do
150: curr_time = get_current_time (0);
151: while ((long int)(get_current_time (0) - vsyncmintime) < 0);
152: }
153: vsyncmintime = get_current_time (1) + vsynctime;
154: vsyncmintime_valid = 1;
1.1.1.2 ! root 155: nr_gtod_done = 0;
1.1 root 156: }
157: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.