|
|
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:
54: int rpt_available = 0;
55:
56: int is_lastline;
57: volatile int blocking_on_sound;
58:
59: void reset_frame_rate_hack (void)
60: {
61: if (currprefs.m68k_speed != -1)
62: return;
63:
64: if (! rpt_available) {
65: currprefs.m68k_speed = 0;
66: return;
67: }
68:
69: vsyncmintime_valid = 0;
70: is_lastline = 0;
71: vsyncmintime = get_current_time(1);
72: vsyncmintime += vsynctime;
73: write_log ("Resetting frame rate hack\n");
74: }
75:
76: void compute_vsynctime (void)
77: {
78: vsynctime = syncbase / vblank_hz;
79: if (use_gtod)
80: vsynctime -= gtod_resolution < 100 ? 100 : gtod_resolution;
81: if (currprefs.produce_sound > 1) {
82: vsynctime = vsynctime * 19 / 20;
83: }
84: }
85:
86: void time_vsync (void)
87: {
88: if (vsyncmintime_valid) {
89: frame_time_t measured = vsyncmintime - first_measured_gtod;
90: unsigned long ideal;
91: if (nr_gtod_done) {
92: if (use_gtod && gtod_resolution < measured)
93: measured -= gtod_resolution;
94: /* Interval between gettimeofday calls. */
95: measured /= nr_gtod_done;
96:
97: /* syncbase has the number of ticks in one second.
98: Hence, syncbase / 5000 ~= 0.2ms. We want to have at least 100
99: gtod calls per frame. */
100: if (measured < syncbase / 5000) {
101: if (max_gtod_to_skip == ULONG_MAX)
102: max_gtod_to_skip = nr_gtod_to_skip;
103: else
104: max_gtod_to_skip = max_gtod_to_skip * 19 / 20;
105: }
106: }
107: }
108:
109: if (currprefs.m68k_speed == -1) {
110: frame_time_t curr_time = get_current_time (1);
111: /* If we got behind in one frame, try catching up by using the
112: previous vsyncmintime as a base. If we get too far behind,
113: give up and reset. */
114: if (vsyncmintime_valid
115: && curr_time > vsyncmintime
116: && curr_time < vsyncmintime + vsynctime / 2)
117: vsyncmintime += vsynctime;
118: else
119: vsyncmintime = curr_time + vsynctime;
120: nr_gtod_done = 0;
121: vsyncmintime_valid = 1;
122: } else {
123: if (vsyncmintime_valid
124: && (use_gtod
125: #ifdef RPT_WORKS_OK
126: || RPT_WORKS_OK
127: #endif
128: ))
129: {
130: frame_time_t curr_time;
131: do
132: curr_time = get_current_time (0);
133: while ((long int)(get_current_time (0) - vsyncmintime) < 0);
134: }
135: vsyncmintime = get_current_time (1) + vsynctime;
136: vsyncmintime_valid = 1;
137: }
138: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.