|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Events
1.1.1.4 root 5: * These are best for low-frequency events. Having too many of them,
6: * or using them for events that occur too frequently, can cause massive
7: * slowdown.
1.1.1.3 root 8: *
1.1.1.4 root 9: * Copyright 1995-1998 Bernd Schmidt
1.1 root 10: */
11:
1.1.1.4 root 12: #include "machdep/rpt.h"
1.1.1.9 root 13:
1.1.1.13! root 14: extern int use_gtod;
! 15:
1.1.1.4 root 16: extern frame_time_t vsynctime, vsyncmintime;
1.1.1.13! root 17: extern frame_time_t gtod_resolution;
! 18: extern int vsyncmintime_valid;
! 19:
! 20: extern frame_time_t first_measured_gtod;
! 21: extern unsigned long gtod_secs;
! 22: extern unsigned long nr_gtod_to_skip;
! 23: extern unsigned long nr_gtod_done, gtod_counter;
! 24:
1.1.1.4 root 25: extern int rpt_available;
26:
1.1.1.13! root 27: extern void reset_frame_rate_hack (void);
1.1.1.11 root 28: extern void compute_vsynctime (void);
1.1.1.13! root 29: extern void time_vsync (void);
! 30:
! 31: extern unsigned long currcycle, nextevent;
! 32:
! 33: extern int is_lastline;
! 34: extern volatile int blocking_on_sound;
1.1.1.11 root 35:
1.1 root 36: typedef void (*evfunc)(void);
37:
38: struct ev
39: {
40: int active;
41: unsigned long int evtime, oldcycles;
42: evfunc handler;
43: };
44:
1.1.1.3 root 45: enum {
1.1.1.9 root 46: ev_hsync, ev_copper, ev_audio, ev_cia, ev_blitter, ev_disk,
1.1 root 47: ev_max
48: };
49:
50: extern struct ev eventtab[ev_max];
51:
1.1.1.13! root 52: STATIC_INLINE frame_time_t get_current_time (int redo_secs)
! 53: {
! 54: if (use_gtod) {
! 55: struct timeval tv;
! 56: gettimeofday (&tv, NULL);
! 57: if (redo_secs)
! 58: gtod_secs = tv.tv_sec;
! 59: return tv.tv_usec + (tv.tv_sec - gtod_secs) * 1000000;
! 60: }
! 61: return read_processor_time ();
! 62: }
! 63:
1.1.1.5 root 64: STATIC_INLINE void events_schedule (void)
1.1 root 65: {
66: int i;
1.1.1.3 root 67:
1.1 root 68: unsigned long int mintime = ~0L;
1.1.1.9 root 69: for (i = 0; i < ev_max; i++) {
1.1.1.3 root 70: if (eventtab[i].active) {
1.1.1.9 root 71: unsigned long int eventtime = eventtab[i].evtime - currcycle;
1.1 root 72: if (eventtime < mintime)
1.1.1.3 root 73: mintime = eventtime;
1.1 root 74: }
75: }
1.1.1.9 root 76: nextevent = currcycle + mintime;
1.1 root 77: }
78:
1.1.1.5 root 79: STATIC_INLINE void do_cycles_slow (unsigned long cycles_to_add)
1.1 root 80: {
1.1.1.13! root 81: if (blocking_on_sound)
1.1.1.3 root 82: return;
1.1.1.4 root 83:
1.1.1.13! root 84: if (is_lastline
! 85: && eventtab[ev_hsync].evtime - currcycle <= cycles_to_add)
! 86: {
! 87: static int n_skipped = 0;
! 88: frame_time_t curr;
! 89:
! 90: if (gtod_counter++ < nr_gtod_to_skip)
! 91: return;
! 92: gtod_counter = 0;
! 93: curr = get_current_time (0);
! 94: if (is_lastline == 1) {
! 95: is_lastline = 2;
! 96: first_measured_gtod = curr;
! 97: }
! 98:
! 99: if ((long int)(curr - vsyncmintime) < 0) {
! 100: nr_gtod_done++;
! 101: return;
! 102: }
! 103: #if 0
! 104: printf ("skipped %d times\n", nr_gtod_done);
! 105: #endif
! 106: }
! 107:
1.1.1.9 root 108: while ((nextevent - currcycle) <= cycles_to_add) {
1.1.1.12 root 109: int i;
110: cycles_to_add -= (nextevent - currcycle);
111: currcycle = nextevent;
1.1.1.9 root 112:
1.1.1.12 root 113: for (i = 0; i < ev_max; i++) {
1.1.1.9 root 114: if (eventtab[i].active && eventtab[i].evtime == currcycle) {
115: (*eventtab[i].handler)();
1.1 root 116: }
117: }
1.1.1.12 root 118: events_schedule();
1.1 root 119: }
1.1.1.9 root 120: currcycle += cycles_to_add;
1.1 root 121: }
122:
1.1.1.5 root 123: STATIC_INLINE void do_cycles_fast (void)
1.1 root 124: {
1.1.1.9 root 125: if (is_lastline && eventtab[ev_hsync].evtime - currcycle <= 1
1.1.1.3 root 126: && (long int)(read_processor_time () - vsyncmintime) < 0)
127: return;
1.1.1.4 root 128:
1.1.1.9 root 129: currcycle++;
130: if (nextevent == currcycle) {
1.1 root 131: int i;
1.1.1.3 root 132:
1.1.1.4 root 133: for (i = 0; i < ev_max; i++) {
1.1.1.9 root 134: if (eventtab[i].active && eventtab[i].evtime == currcycle) {
1.1.1.4 root 135: (*eventtab[i].handler) ();
1.1 root 136: }
137: }
138: events_schedule();
139: }
140:
141: }
142:
1.1.1.10 root 143: /* This is a special-case function. Normally, all events should lie in the
144: future; they should only ever be active at the current cycle during
145: do_cycles. However, a snapshot is saved during do_cycles, and so when
146: restoring it, we may have other events pending. */
147: STATIC_INLINE void handle_active_events (void)
148: {
149: int i;
150: for (i = 0; i < ev_max; i++) {
151: if (eventtab[i].active && eventtab[i].evtime == currcycle) {
152: (*eventtab[i].handler)();
153: }
154: }
155: }
156:
1.1.1.9 root 157: STATIC_INLINE unsigned long get_cycles (void)
158: {
159: return currcycle;
160: }
161:
1.1.1.10 root 162: extern void init_eventtab (void);
163:
1.1.1.3 root 164: #if /* M68K_SPEED == 1 */ 0
1.1 root 165: #define do_cycles do_cycles_fast
166: #else
167: #define do_cycles do_cycles_slow
168: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.